From 4b0753269f45d2aa254827bb720e96056a074539 Mon Sep 17 00:00:00 2001 From: Mikhail Bautin Date: Thu, 19 May 2022 12:08:12 -0700 Subject: Imoprt from https://people.redhat.com/~dhowells/keyutils/keyutils-1.6.1.tar.bz2 --- .gitignore | 11 + LICENCE.GPL | 339 ++++ LICENCE.LGPL | 504 +++++ Makefile | 313 ++++ README | 15 + SUBMITTING_PATCHES | 45 + dns.afsdb.c | 335 ++++ key.dns.h | 70 + key.dns_resolver.c | 565 ++++++ keyctl.c | 2375 ++++++++++++++++++++++++ keyutils.c | 880 +++++++++ keyutils.h | 269 +++ keyutils.spec | 302 +++ libkeyutils.pc.in | 8 + man/asymmetric-key.7 | 232 +++ man/find_key_by_type_and_name.3 | 65 + man/key.dns_resolver.8 | 34 + man/keyctl.1 | 908 +++++++++ man/keyctl.3 | 123 ++ man/keyctl_capabilities.3 | 109 ++ man/keyctl_chown.3 | 88 + man/keyctl_clear.3 | 74 + man/keyctl_describe.3 | 112 ++ man/keyctl_dh_compute.3 | 168 ++ man/keyctl_get_keyring_ID.3 | 96 + man/keyctl_get_persistent.3 | 114 ++ man/keyctl_get_security.3 | 102 + man/keyctl_instantiate.3 | 191 ++ man/keyctl_invalidate.3 | 76 + man/keyctl_join_session_keyring.3 | 84 + man/keyctl_link.3 | 108 ++ man/keyctl_move.3 | 109 ++ man/keyctl_pkey_decrypt.3 | 1 + man/keyctl_pkey_encrypt.3 | 113 ++ man/keyctl_pkey_query.3 | 137 ++ man/keyctl_pkey_sign.3 | 133 ++ man/keyctl_pkey_verify.3 | 1 + man/keyctl_read.3 | 112 ++ man/keyctl_restrict_keyring.3 | 82 + man/keyctl_revoke.3 | 73 + man/keyctl_search.3 | 138 ++ man/keyctl_session_to_parent.3 | 77 + man/keyctl_set_reqkey_keyring.3 | 101 + man/keyctl_set_timeout.3 | 81 + man/keyctl_setperm.3 | 130 ++ man/keyctl_update.3 | 96 + man/keyutils.7 | 105 ++ man/recursive_key_scan.3 | 90 + man/request-key.8 | 61 + man/request-key.conf.5 | 145 ++ request-key-debug.sh | 33 + request-key.c | 955 ++++++++++ request-key.conf | 41 + tests/Makefile | 76 + tests/PURPOSE | 82 + tests/bugzillas/bz1031154/runtest.sh | 104 ++ tests/bugzillas/bz1033467/runtest.sh | 68 + tests/bugzillas/bz1071346/runtest.sh | 79 + tests/keyctl/add/bad-args/runtest.sh | 74 + tests/keyctl/add/noargs/runtest.sh | 35 + tests/keyctl/add/useradd/runtest.sh | 53 + tests/keyctl/clear/bad-args/runtest.sh | 39 + tests/keyctl/clear/noargs/runtest.sh | 23 + tests/keyctl/clear/valid/runtest.sh | 96 + tests/keyctl/describing/bad-args/runtest.sh | 38 + tests/keyctl/describing/noargs/runtest.sh | 25 + tests/keyctl/describing/valid/runtest.sh | 71 + tests/keyctl/dh_compute/bad-args/runtest.sh | 89 + tests/keyctl/dh_compute/noargs/runtest.sh | 30 + tests/keyctl/dh_compute/valid/runtest.sh | 266 +++ tests/keyctl/instantiating/bad-args/runtest.sh | 55 + tests/keyctl/instantiating/noargs/runtest.sh | 36 + tests/keyctl/invalidate/bad-args/runtest.sh | 40 + tests/keyctl/invalidate/noargs/runtest.sh | 29 + tests/keyctl/invalidate/valid/runtest.sh | 80 + tests/keyctl/link/bad-args/runtest.sh | 47 + tests/keyctl/link/noargs/runtest.sh | 27 + tests/keyctl/link/recursion/runtest.sh | 185 ++ tests/keyctl/link/valid/runtest.sh | 139 ++ tests/keyctl/listing/bad-args/runtest.sh | 38 + tests/keyctl/listing/noargs/runtest.sh | 23 + tests/keyctl/listing/valid/runtest.sh | 109 ++ tests/keyctl/move/bad-args/runtest.sh | 64 + tests/keyctl/move/noargs/runtest.sh | 39 + tests/keyctl/move/recursion/runtest.sh | 213 +++ tests/keyctl/move/valid/runtest.sh | 230 +++ tests/keyctl/newring/bad-args/runtest.sh | 49 + tests/keyctl/newring/noargs/runtest.sh | 27 + tests/keyctl/newring/valid/runtest.sh | 61 + tests/keyctl/noargs/runtest.sh | 24 + tests/keyctl/padd/bad-args/runtest.sh | 74 + tests/keyctl/padd/noargs/runtest.sh | 31 + tests/keyctl/padd/useradd/runtest.sh | 91 + tests/keyctl/permitting/bad-args/runtest.sh | 49 + tests/keyctl/permitting/noargs/runtest.sh | 30 + tests/keyctl/permitting/valid/runtest.sh | 99 + tests/keyctl/pupdate/bad-args/runtest.sh | 39 + tests/keyctl/pupdate/noargs/runtest.sh | 23 + tests/keyctl/pupdate/userupdate/runtest.sh | 38 + tests/keyctl/reading/bad-args/runtest.sh | 42 + tests/keyctl/reading/noargs/runtest.sh | 25 + tests/keyctl/reading/valid/runtest.sh | 96 + tests/keyctl/requesting/bad-args/runtest.sh | 128 ++ tests/keyctl/requesting/noargs/runtest.sh | 43 + tests/keyctl/requesting/piped/runtest.sh | 106 ++ tests/keyctl/requesting/valid/runtest.sh | 106 ++ tests/keyctl/restrict/bad-args/runtest.sh | 50 + tests/keyctl/restrict/valid/runtest.sh | 512 +++++ tests/keyctl/revoke/bad-args/runtest.sh | 25 + tests/keyctl/revoke/noargs/runtest.sh | 22 + tests/keyctl/revoke/valid/runtest.sh | 75 + tests/keyctl/search/bad-args/runtest.sh | 87 + tests/keyctl/search/noargs/runtest.sh | 31 + tests/keyctl/search/valid/runtest.sh | 186 ++ tests/keyctl/session/bad-args/runtest.sh | 32 + tests/keyctl/session/valid/runtest.sh | 42 + tests/keyctl/show/noargs/runtest.sh | 51 + tests/keyctl/show/valid/runtest.sh | 84 + tests/keyctl/supports/bad-args/runtest.sh | 23 + tests/keyctl/supports/valid/runtest.sh | 23 + tests/keyctl/timeout/bad-args/runtest.sh | 34 + tests/keyctl/timeout/noargs/runtest.sh | 26 + tests/keyctl/timeout/valid/runtest.sh | 130 ++ tests/keyctl/unlink/all/runtest.sh | 103 + tests/keyctl/unlink/bad-args/runtest.sh | 47 + tests/keyctl/unlink/noargs/runtest.sh | 30 + tests/keyctl/unlink/valid/runtest.sh | 99 + tests/keyctl/update/bad-args/runtest.sh | 39 + tests/keyctl/update/noargs/runtest.sh | 27 + tests/keyctl/update/userupdate/runtest.sh | 38 + tests/prepare.inc.sh | 138 ++ tests/runtest.sh | 35 + tests/toolbox.inc.sh | 1261 +++++++++++++ tests/vercmp.sh | 31 + tests/version.inc.sh | 199 ++ version.lds | 100 + 136 files changed, 18892 insertions(+) create mode 100644 .gitignore create mode 100644 LICENCE.GPL create mode 100644 LICENCE.LGPL create mode 100644 Makefile create mode 100644 README create mode 100644 SUBMITTING_PATCHES create mode 100644 dns.afsdb.c create mode 100644 key.dns.h create mode 100644 key.dns_resolver.c create mode 100644 keyctl.c create mode 100644 keyutils.c create mode 100644 keyutils.h create mode 100644 keyutils.spec create mode 100644 libkeyutils.pc.in create mode 100644 man/asymmetric-key.7 create mode 100644 man/find_key_by_type_and_name.3 create mode 100644 man/key.dns_resolver.8 create mode 100644 man/keyctl.1 create mode 100644 man/keyctl.3 create mode 100644 man/keyctl_capabilities.3 create mode 100644 man/keyctl_chown.3 create mode 100644 man/keyctl_clear.3 create mode 100644 man/keyctl_describe.3 create mode 100644 man/keyctl_dh_compute.3 create mode 100644 man/keyctl_get_keyring_ID.3 create mode 100644 man/keyctl_get_persistent.3 create mode 100644 man/keyctl_get_security.3 create mode 100644 man/keyctl_instantiate.3 create mode 100644 man/keyctl_invalidate.3 create mode 100644 man/keyctl_join_session_keyring.3 create mode 100644 man/keyctl_link.3 create mode 100644 man/keyctl_move.3 create mode 100644 man/keyctl_pkey_decrypt.3 create mode 100644 man/keyctl_pkey_encrypt.3 create mode 100644 man/keyctl_pkey_query.3 create mode 100644 man/keyctl_pkey_sign.3 create mode 100644 man/keyctl_pkey_verify.3 create mode 100644 man/keyctl_read.3 create mode 100644 man/keyctl_restrict_keyring.3 create mode 100644 man/keyctl_revoke.3 create mode 100644 man/keyctl_search.3 create mode 100644 man/keyctl_session_to_parent.3 create mode 100644 man/keyctl_set_reqkey_keyring.3 create mode 100644 man/keyctl_set_timeout.3 create mode 100644 man/keyctl_setperm.3 create mode 100644 man/keyctl_update.3 create mode 100644 man/keyutils.7 create mode 100644 man/recursive_key_scan.3 create mode 100644 man/request-key.8 create mode 100644 man/request-key.conf.5 create mode 100755 request-key-debug.sh create mode 100644 request-key.c create mode 100644 request-key.conf create mode 100644 tests/Makefile create mode 100644 tests/PURPOSE create mode 100644 tests/bugzillas/bz1031154/runtest.sh create mode 100644 tests/bugzillas/bz1033467/runtest.sh create mode 100644 tests/bugzillas/bz1071346/runtest.sh create mode 100644 tests/keyctl/add/bad-args/runtest.sh create mode 100644 tests/keyctl/add/noargs/runtest.sh create mode 100644 tests/keyctl/add/useradd/runtest.sh create mode 100644 tests/keyctl/clear/bad-args/runtest.sh create mode 100644 tests/keyctl/clear/noargs/runtest.sh create mode 100644 tests/keyctl/clear/valid/runtest.sh create mode 100644 tests/keyctl/describing/bad-args/runtest.sh create mode 100644 tests/keyctl/describing/noargs/runtest.sh create mode 100644 tests/keyctl/describing/valid/runtest.sh create mode 100644 tests/keyctl/dh_compute/bad-args/runtest.sh create mode 100644 tests/keyctl/dh_compute/noargs/runtest.sh create mode 100644 tests/keyctl/dh_compute/valid/runtest.sh create mode 100644 tests/keyctl/instantiating/bad-args/runtest.sh create mode 100644 tests/keyctl/instantiating/noargs/runtest.sh create mode 100644 tests/keyctl/invalidate/bad-args/runtest.sh create mode 100644 tests/keyctl/invalidate/noargs/runtest.sh create mode 100644 tests/keyctl/invalidate/valid/runtest.sh create mode 100644 tests/keyctl/link/bad-args/runtest.sh create mode 100644 tests/keyctl/link/noargs/runtest.sh create mode 100644 tests/keyctl/link/recursion/runtest.sh create mode 100644 tests/keyctl/link/valid/runtest.sh create mode 100644 tests/keyctl/listing/bad-args/runtest.sh create mode 100644 tests/keyctl/listing/noargs/runtest.sh create mode 100644 tests/keyctl/listing/valid/runtest.sh create mode 100644 tests/keyctl/move/bad-args/runtest.sh create mode 100644 tests/keyctl/move/noargs/runtest.sh create mode 100644 tests/keyctl/move/recursion/runtest.sh create mode 100644 tests/keyctl/move/valid/runtest.sh create mode 100644 tests/keyctl/newring/bad-args/runtest.sh create mode 100644 tests/keyctl/newring/noargs/runtest.sh create mode 100644 tests/keyctl/newring/valid/runtest.sh create mode 100644 tests/keyctl/noargs/runtest.sh create mode 100644 tests/keyctl/padd/bad-args/runtest.sh create mode 100644 tests/keyctl/padd/noargs/runtest.sh create mode 100644 tests/keyctl/padd/useradd/runtest.sh create mode 100644 tests/keyctl/permitting/bad-args/runtest.sh create mode 100644 tests/keyctl/permitting/noargs/runtest.sh create mode 100644 tests/keyctl/permitting/valid/runtest.sh create mode 100644 tests/keyctl/pupdate/bad-args/runtest.sh create mode 100644 tests/keyctl/pupdate/noargs/runtest.sh create mode 100644 tests/keyctl/pupdate/userupdate/runtest.sh create mode 100644 tests/keyctl/reading/bad-args/runtest.sh create mode 100644 tests/keyctl/reading/noargs/runtest.sh create mode 100644 tests/keyctl/reading/valid/runtest.sh create mode 100644 tests/keyctl/requesting/bad-args/runtest.sh create mode 100644 tests/keyctl/requesting/noargs/runtest.sh create mode 100644 tests/keyctl/requesting/piped/runtest.sh create mode 100644 tests/keyctl/requesting/valid/runtest.sh create mode 100644 tests/keyctl/restrict/bad-args/runtest.sh create mode 100644 tests/keyctl/restrict/valid/runtest.sh create mode 100644 tests/keyctl/revoke/bad-args/runtest.sh create mode 100644 tests/keyctl/revoke/noargs/runtest.sh create mode 100644 tests/keyctl/revoke/valid/runtest.sh create mode 100644 tests/keyctl/search/bad-args/runtest.sh create mode 100644 tests/keyctl/search/noargs/runtest.sh create mode 100644 tests/keyctl/search/valid/runtest.sh create mode 100644 tests/keyctl/session/bad-args/runtest.sh create mode 100644 tests/keyctl/session/valid/runtest.sh create mode 100644 tests/keyctl/show/noargs/runtest.sh create mode 100644 tests/keyctl/show/valid/runtest.sh create mode 100644 tests/keyctl/supports/bad-args/runtest.sh create mode 100644 tests/keyctl/supports/valid/runtest.sh create mode 100644 tests/keyctl/timeout/bad-args/runtest.sh create mode 100644 tests/keyctl/timeout/noargs/runtest.sh create mode 100644 tests/keyctl/timeout/valid/runtest.sh create mode 100644 tests/keyctl/unlink/all/runtest.sh create mode 100644 tests/keyctl/unlink/bad-args/runtest.sh create mode 100644 tests/keyctl/unlink/noargs/runtest.sh create mode 100644 tests/keyctl/unlink/valid/runtest.sh create mode 100644 tests/keyctl/update/bad-args/runtest.sh create mode 100644 tests/keyctl/update/noargs/runtest.sh create mode 100644 tests/keyctl/update/userupdate/runtest.sh create mode 100644 tests/prepare.inc.sh create mode 100644 tests/runtest.sh create mode 100644 tests/toolbox.inc.sh create mode 100644 tests/vercmp.sh create mode 100644 tests/version.inc.sh create mode 100644 version.lds diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..0ac39edf52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*~ +*.o +*.os +*.so +*.a +*.so.* +/keyctl +/request-key +/key.dns_resolver +/rpmbuild +test.out diff --git a/LICENCE.GPL b/LICENCE.GPL new file mode 100644 index 0000000000..4505352518 --- /dev/null +++ b/LICENCE.GPL @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/LICENCE.LGPL b/LICENCE.LGPL new file mode 100644 index 0000000000..519334a885 --- /dev/null +++ b/LICENCE.LGPL @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..5f8b16321c --- /dev/null +++ b/Makefile @@ -0,0 +1,313 @@ +CPPFLAGS := -I. +CFLAGS := -g -Wall -Werror +INSTALL := install +DESTDIR := +SPECFILE := keyutils.spec +NO_GLIBC_KEYERR := 0 +NO_ARLIB := 0 +NO_SOLIB := 0 +ETCDIR := /etc +BINDIR := /bin +SBINDIR := /sbin +SHAREDIR := /usr/share/keyutils +MANDIR := /usr/share/man +MAN1 := $(MANDIR)/man1 +MAN3 := $(MANDIR)/man3 +MAN5 := $(MANDIR)/man5 +MAN7 := $(MANDIR)/man7 +MAN8 := $(MANDIR)/man8 +INCLUDEDIR := /usr/include +LN := ln +LNS := $(LN) -sf +PREFIX := /usr + +############################################################################### +# +# Determine the current package version from the specfile +# +############################################################################### +vermajor := $(shell grep "%define vermajor" $(SPECFILE)) +verminor := $(shell grep "%define verminor" $(SPECFILE)) +MAJOR := $(word 3,$(vermajor)) +MINOR := $(word 3,$(verminor)) +VERSION := $(MAJOR).$(MINOR) + +TARBALL := keyutils-$(VERSION).tar +ZTARBALL := $(TARBALL).bz2 + +############################################################################### +# +# Determine the current library version from the version script +# +############################################################################### +libversion := $(filter KEYUTILS_%,$(shell grep ^KEYUTILS_ version.lds)) +libversion := $(lastword $(libversion)) +libversion := $(lastword $(libversion)) +APIVERSION := $(subst KEYUTILS_,,$(libversion)) +vernumbers := $(subst ., ,$(APIVERSION)) +APIMAJOR := $(firstword $(vernumbers)) + +ARLIB := libkeyutils.a +DEVELLIB := libkeyutils.so +SONAME := libkeyutils.so.$(APIMAJOR) +LIBNAME := libkeyutils.so.$(APIVERSION) + +############################################################################### +# +# Guess at the appropriate lib directory and word size +# +############################################################################### +ifeq ($(origin LIBDIR),undefined) +LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') +endif +ifeq ($(origin USRLIBDIR),undefined) +USRLIBDIR := $(patsubst /lib/%,/usr/lib/%,$(LIBDIR)) +endif +BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit + +ifeq ($(origin CFLAGS),undefined) +ifeq ($(BUILDFOR),32-bit) +CFLAGS += -m32 +LIBDIR := /lib +USRLIBDIR := /usr/lib +else +ifeq ($(BUILDFOR),64-bit) +CFLAGS += -m64 +LIBDIR := /lib64 +USRLIBDIR := /usr/lib64 +endif +endif +endif + +PKGCONFIG := libkeyutils.pc +PKGCONFIG_DIR := pkgconfig + +############################################################################### +# +# This is necessary if glibc doesn't know about the key management error codes +# +############################################################################### +ifeq ($(NO_GLIBC_KEYERR),1) +CFLAGS += -DNO_GLIBC_KEYERR +LIBLIBS := -ldl -lc +else +LIBLIBS := +endif + +############################################################################### +# +# Normal build rule +# +############################################################################### +all: keyctl request-key key.dns_resolver + +############################################################################### +# +# Build the libraries +# +############################################################################### +#RPATH = -Wl,-rpath,$(LIBDIR) + +VCPPFLAGS := -DPKGBUILD="\"$(shell date -u +%F)\"" +VCPPFLAGS += -DPKGVERSION="\"keyutils-$(VERSION)\"" +VCPPFLAGS += -DAPIVERSION="\"libkeyutils-$(APIVERSION)\"" + +ifeq ($(NO_ARLIB),0) +all: $(ARLIB) +$(ARLIB): keyutils.o + $(AR) rcs $@ $< + +keyutils.o: keyutils.c keyutils.h Makefile + $(CC) $(CPPFLAGS) $(VCPPFLAGS) $(CFLAGS) -UNO_GLIBC_KEYERR -o $@ -c $< +LIB_DEPENDENCY := libkeyutils.a +endif + + +ifeq ($(NO_SOLIB),0) +all: $(DEVELLIB) +$(DEVELLIB): $(SONAME) + $(LNS) $< $@ + +$(SONAME): $(LIBNAME) + $(LNS) $< $@ + +LIBVERS := -shared -Wl,-soname,$(SONAME) -Wl,--version-script,version.lds + +$(LIBNAME): keyutils.os version.lds Makefile + $(CC) $(CFLAGS) -fPIC $(LDFLAGS) $(LIBVERS) -o $@ keyutils.os $(LIBLIBS) + +keyutils.os: keyutils.c keyutils.h Makefile + $(CC) $(CPPFLAGS) $(VCPPFLAGS) $(CFLAGS) -fPIC -o $@ -c $< +LIB_DEPENDENCY := $(DEVELLIB) +endif + +############################################################################### +# +# Build the programs +# +############################################################################### +%.o: %.c keyutils.h Makefile + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +keyctl: keyctl.o $(LIB_DEPENDENCY) + $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ $< -lkeyutils + +request-key: request-key.o $(LIB_DEPENDENCY) + $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ $< -lkeyutils + +key.dns_resolver: key.dns_resolver.o dns.afsdb.o $(LIB_DEPENDENCY) + $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ \ + key.dns_resolver.o dns.afsdb.o -lkeyutils -lresolv + +key.dns_resolver.o: key.dns_resolver.c key.dns.h +dns.afsdb.o: dns.afsdb.c key.dns.h + +############################################################################### +# +# Install everything +# +############################################################################### +pkgconfig: + sed \ + -e 's,@VERSION\@,$(VERSION),g' \ + -e 's,@prefix\@,$(PREFIX),g' \ + -e 's,@exec_prefix\@,$(PREFIX),g' \ + -e 's,@libdir\@,$(USRLIBDIR),g' \ + -e 's,@includedir\@,$(INCLUDEDIR),g' \ + < $(PKGCONFIG).in > $(PKGCONFIG) || rm $(PKGCONFIG) + +install: all +ifeq ($(NO_ARLIB),0) + $(INSTALL) -D -m 0644 $(ARLIB) $(DESTDIR)$(USRLIBDIR)/$(ARLIB) +endif +ifeq ($(NO_SOLIB),0) + $(INSTALL) -D $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) + $(LNS) $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) + mkdir -p $(DESTDIR)$(USRLIBDIR) + $(LNS) $(LIBDIR)/$(SONAME) $(DESTDIR)$(USRLIBDIR)/$(DEVELLIB) + sed \ + -e 's,@VERSION\@,$(VERSION),g' \ + -e 's,@prefix\@,$(PREFIX),g' \ + -e 's,@exec_prefix\@,$(PREFIX),g' \ + -e 's,@libdir\@,$(USRLIBDIR),g' \ + -e 's,@includedir\@,$(INCLUDEDIR),g' \ + < $(PKGCONFIG).in > $(PKGCONFIG) || rm $(PKGCONFIG) + $(INSTALL) -D $(PKGCONFIG) $(DESTDIR)$(LIBDIR)/$(PKGCONFIG_DIR)/$(PKGCONFIG) + rm $(PKGCONFIG) +endif + $(INSTALL) -D keyctl $(DESTDIR)$(BINDIR)/keyctl + $(INSTALL) -D request-key $(DESTDIR)$(SBINDIR)/request-key + $(INSTALL) -D request-key-debug.sh $(DESTDIR)$(SHAREDIR)/request-key-debug.sh + $(INSTALL) -D key.dns_resolver $(DESTDIR)$(SBINDIR)/key.dns_resolver + $(INSTALL) -D -m 0644 request-key.conf $(DESTDIR)$(ETCDIR)/request-key.conf + mkdir -p $(DESTDIR)$(ETCDIR)/request-key.d + mkdir -p $(DESTDIR)$(MAN1) + $(INSTALL) -m 0644 $(wildcard man/*.1) $(DESTDIR)$(MAN1) + mkdir -p $(DESTDIR)$(MAN3) + $(INSTALL) -m 0644 $(wildcard man/*.3) $(DESTDIR)$(MAN3) + mkdir -p $(DESTDIR)$(MAN5) + $(INSTALL) -m 0644 $(wildcard man/*.5) $(DESTDIR)$(MAN5) + mkdir -p $(DESTDIR)$(MAN7) + $(INSTALL) -m 0644 $(wildcard man/*.7) $(DESTDIR)$(MAN7) + mkdir -p $(DESTDIR)$(MAN8) + $(INSTALL) -m 0644 $(wildcard man/*.8) $(DESTDIR)$(MAN8) + $(LNS) keyctl_describe.3 $(DESTDIR)$(MAN3)/keyctl_describe_alloc.3 + $(LNS) keyctl_get_security.3 $(DESTDIR)$(MAN3)/keyctl_get_security_alloc.3 + $(LNS) keyctl_instantiate.3 $(DESTDIR)$(MAN3)/keyctl_instantiate_iov.3 + $(LNS) keyctl_instantiate.3 $(DESTDIR)$(MAN3)/keyctl_reject.3 + $(LNS) keyctl_instantiate.3 $(DESTDIR)$(MAN3)/keyctl_negate.3 + $(LNS) keyctl_instantiate.3 $(DESTDIR)$(MAN3)/keyctl_assume_authority.3 + $(LNS) keyctl_link.3 $(DESTDIR)$(MAN3)/keyctl_unlink.3 + $(LNS) keyctl_read.3 $(DESTDIR)$(MAN3)/keyctl_read_alloc.3 + $(LNS) recursive_key_scan.3 $(DESTDIR)$(MAN3)/recursive_session_key_scan.3 + $(LNS) keyctl_dh_compute.3 $(DESTDIR)$(MAN3)/keyctl_dh_compute_alloc.3 + $(LNS) keyctl_dh_compute.3 $(DESTDIR)$(MAN3)/keyctl_dh_compute_kdf.3 + $(INSTALL) -D -m 0644 keyutils.h $(DESTDIR)$(INCLUDEDIR)/keyutils.h + +############################################################################### +# +# Run tests +# +############################################################################### +test: + $(MAKE) -C tests run + +############################################################################### +# +# Clean up +# +############################################################################### +clean: + $(MAKE) -C tests clean + $(RM) libkeyutils.so* libkeyutils.a + $(RM) keyctl request-key key.dns_resolver + $(RM) *.o *.os *~ + $(RM) debugfiles.list debugsources.list + +distclean: clean + $(RM) -r rpmbuild $(TARBALL) + +############################################################################### +# +# Generate a tarball +# +############################################################################### +$(ZTARBALL): + git archive --prefix=keyutils-$(VERSION)/ --format tar -o $(TARBALL) HEAD + bzip2 -9 <$(TARBALL) >$(ZTARBALL) + +tarball: $(ZTARBALL) + +############################################################################### +# +# Generate an RPM +# +############################################################################### +SRCBALL := rpmbuild/SOURCES/$(TARBALL) +ZSRCBALL := rpmbuild/SOURCES/$(ZTARBALL) + +BUILDID := .local +dist := $(word 2,$(shell grep -r "^%dist" /etc/rpm /usr/lib/rpm)) +release3:= $(word 2,$(shell grep ^Release: $(SPECFILE))) +release2:= $(subst %{?dist},$(dist),$(release3)) +release1:= $(subst %{?buildid},$(BUILDID),$(release2)) +release := $(subst %{?distprefix},,$(release1)) +rpmver := $(VERSION)-$(release) +SRPM := rpmbuild/SRPMS/keyutils-$(rpmver).src.rpm + +RPMBUILDDIRS := \ + --define "_srcrpmdir $(CURDIR)/rpmbuild/SRPMS" \ + --define "_rpmdir $(CURDIR)/rpmbuild/RPMS" \ + --define "_sourcedir $(CURDIR)/rpmbuild/SOURCES" \ + --define "_specdir $(CURDIR)/rpmbuild/SPECS" \ + --define "_builddir $(CURDIR)/rpmbuild/BUILD" \ + --define "_buildrootdir $(CURDIR)/rpmbuild/BUILDROOT" + +RPMFLAGS := \ + --define "buildid $(BUILDID)" + +rpm: + mkdir -p rpmbuild + chmod ug-s rpmbuild + mkdir -p rpmbuild/{SPECS,SOURCES,BUILD,BUILDROOT,RPMS,SRPMS} + git archive --prefix=keyutils-$(VERSION)/ --format tar -o $(SRCBALL) HEAD + bzip2 -9 <$(SRCBALL) >$(ZSRCBALL) + rpmbuild -ts $(ZSRCBALL) --define "_srcrpmdir rpmbuild/SRPMS" $(RPMFLAGS) + rpmbuild --rebuild $(SRPM) $(RPMBUILDDIRS) $(RPMFLAGS) + +rpmlint: rpm + rpmlint $(SRPM) $(CURDIR)/rpmbuild/RPMS/*/keyutils-{,libs-,libs-devel-,debuginfo-}$(rpmver).*.rpm + +############################################################################### +# +# Build debugging +# +############################################################################### +show_vars: + @echo VERSION=$(VERSION) + @echo APIVERSION=$(APIVERSION) + @echo LIBDIR=$(LIBDIR) + @echo USRLIBDIR=$(USRLIBDIR) + @echo BUILDFOR=$(BUILDFOR) + @echo SONAME=$(SONAME) + @echo LIBNAME=$(LIBNAME) diff --git a/README b/README new file mode 100644 index 0000000000..5c3d94d406 --- /dev/null +++ b/README @@ -0,0 +1,15 @@ +These tools are used to control the key management system built into the Linux +kernel. + +To build and install the tools and manual pages, run: + + make + make install + +If your glibc does not contain definitions for the new error codes and system +calls, then try: + + make NO_GLIBC_KEYERR=1 + +The tools are licensed under the GPL and the utility library under the LGPL. +Copies of these are included in this tarball. diff --git a/SUBMITTING_PATCHES b/SUBMITTING_PATCHES new file mode 100644 index 0000000000..c5ba909b5c --- /dev/null +++ b/SUBMITTING_PATCHES @@ -0,0 +1,45 @@ + ================== + SUBMITTING PATCHES + ================== + +Patches can be sent to the keyrings@vger.kernel.org mailing list or directly to +David Howells , the author, in a private email. + +When sending patches to be included in keyutils, please certify that your patch +meets the criteria below by including include a sign-off line in your email +which looks like this: + + Signed-off-by: Random J Developer + +This confirms that you are permitted to submit the patch for inclusion in +keyutils under the GPLv2 licence (utilities and documentation) or the LGPLv2.1 +licence (library). The full text of the certificate is as follows: + + Developer's Certificate of Origin v1.1 + ====================================== + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source licences + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + licence and I have the right under that licence to submit that + work with modifications, whether created in whole or in part + by me, under the same open source licence (unless I am + permitted to submit under a different licence), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + and also that: + + (d) I understand and agree that this project and the contribution are + public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source licence(s) involved. diff --git a/dns.afsdb.c b/dns.afsdb.c new file mode 100644 index 0000000000..fa60e04fb2 --- /dev/null +++ b/dns.afsdb.c @@ -0,0 +1,335 @@ +/* + * DNS Resolver Module User-space Helper for AFSDB records + * + * Copyright (C) Wang Lei (wang840925@gmail.com) 2010 + * Authors: Wang Lei (wang840925@gmail.com) + * + * Copyright (C) David Howells (dhowells@redhat.com) 2018 + * + * This is a userspace tool for querying AFSDB RR records in the DNS on behalf + * of the kernel, and converting the VL server addresses to IPv4 format so that + * they can be used by the kAFS filesystem. + * + * As some function like res_init() should use the static library, which is a + * bug of libresolv, that is the reason for cifs.upcall to reimplement. + * + * To use this program, you must tell /sbin/request-key how to invoke it. You + * need to have the keyutils package installed and something like the following + * lines added to your /etc/request-key.conf file: + * + * #OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ... + * ====== ============ =========== ============ ========================== + * create dns_resolver afsdb:* * /sbin/key.dns_resolver %k + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "key.dns.h" + +static unsigned long afs_ttl = ULONG_MAX; + +/* + * + */ +static void afsdb_hosts_to_addrs(ns_msg handle, ns_sect section) +{ + char *vllist[MAX_VLS]; /* list of name servers */ + int vlsnum = 0; /* number of name servers in list */ + int rrnum; + ns_rr rr; + int subtype, i, ret; + unsigned int ttl = UINT_MAX, rr_ttl; + + debug("AFSDB RR count is %d", ns_msg_count(handle, section)); + + /* Look at all the resource records in this section. */ + for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { + /* Expand the resource record number rrnum into rr. */ + if (ns_parserr(&handle, section, rrnum, &rr)) { + _error("ns_parserr failed : %m"); + continue; + } + + /* We're only interested in AFSDB records */ + if (ns_rr_type(rr) == ns_t_afsdb) { + vllist[vlsnum] = malloc(MAXDNAME); + if (!vllist[vlsnum]) + error("Out of memory"); + + subtype = ns_get16(ns_rr_rdata(rr)); + + /* Expand the name server's domain name */ + if (ns_name_uncompress(ns_msg_base(handle), + ns_msg_end(handle), + ns_rr_rdata(rr) + 2, + vllist[vlsnum], + MAXDNAME) < 0) + error("ns_name_uncompress failed"); + + rr_ttl = ns_rr_ttl(rr); + if (ttl > rr_ttl) + ttl = rr_ttl; + + /* Check the domain name we've just unpacked and add it to + * the list of VL servers if it is not a duplicate. + * If it is a duplicate, just ignore it. + */ + for (i = 0; i < vlsnum; i++) + if (strcasecmp(vllist[i], vllist[vlsnum]) == 0) + goto next_one; + + /* Turn the hostname into IP addresses */ + ret = dns_resolver(vllist[vlsnum], NULL); + if (ret) { + debug("AFSDB RR can't resolve." + "subtype:%d, server name:%s, netmask:%u", + subtype, vllist[vlsnum], mask); + goto next_one; + } + + info("AFSDB RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u", + subtype, vllist[vlsnum], + (int)payload[payload_index - 1].iov_len, + (int)payload[payload_index - 1].iov_len, + (char *)payload[payload_index - 1].iov_base, + ttl); + + /* prepare for the next record */ + vlsnum++; + continue; + + next_one: + free(vllist[vlsnum]); + } + } + + afs_ttl = ttl; + info("ttl: %u", ttl); +} + +/* + * + */ +static void srv_hosts_to_addrs(ns_msg handle, ns_sect section) +{ + char *vllist[MAX_VLS]; /* list of name servers */ + int vlsnum = 0; /* number of name servers in list */ + int rrnum; + ns_rr rr; + int subtype, i, ret; + unsigned short pref, weight, port; + unsigned int ttl = UINT_MAX, rr_ttl; + char sport[8]; + + debug("SRV RR count is %d", ns_msg_count(handle, section)); + + /* Look at all the resource records in this section. */ + for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { + /* Expand the resource record number rrnum into rr. */ + if (ns_parserr(&handle, section, rrnum, &rr)) { + _error("ns_parserr failed : %m"); + continue; + } + + if (ns_rr_type(rr) == ns_t_srv) { + vllist[vlsnum] = malloc(MAXDNAME); + if (!vllist[vlsnum]) + error("Out of memory"); + + subtype = ns_get16(ns_rr_rdata(rr)); + + /* Expand the name server's domain name */ + if (ns_name_uncompress(ns_msg_base(handle), + ns_msg_end(handle), + ns_rr_rdata(rr) + 6, + vllist[vlsnum], + MAXDNAME) < 0) { + _error("ns_name_uncompress failed"); + continue; + } + + rr_ttl = ns_rr_ttl(rr); + if (ttl > rr_ttl) + ttl = rr_ttl; + + pref = ns_get16(ns_rr_rdata(rr)); + weight = ns_get16(ns_rr_rdata(rr) + 2); + port = ns_get16(ns_rr_rdata(rr) + 4); + info("rdata %u %u %u", pref, weight, port); + + sprintf(sport, "+%hu", port); + + /* Check the domain name we've just unpacked and add it to + * the list of VL servers if it is not a duplicate. + * If it is a duplicate, just ignore it. + */ + for (i = 0; i < vlsnum; i++) + if (strcasecmp(vllist[i], vllist[vlsnum]) == 0) + goto next_one; + + /* Turn the hostname into IP addresses */ + ret = dns_resolver(vllist[vlsnum], sport); + if (ret) { + debug("SRV RR can't resolve." + "subtype:%d, server name:%s, netmask:%u", + subtype, vllist[vlsnum], mask); + goto next_one; + } + + info("SRV RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u", + subtype, vllist[vlsnum], + (int)payload[payload_index - 1].iov_len, + (int)payload[payload_index - 1].iov_len, + (char *)payload[payload_index - 1].iov_base, + ttl); + + /* prepare for the next record */ + vlsnum++; + continue; + + next_one: + free(vllist[vlsnum]); + } + } + + afs_ttl = ttl; + info("ttl: %u", ttl); +} + +/* + * Look up an AFSDB record to get the VL server addresses. + */ +static int dns_query_AFSDB(const char *cell) +{ + int response_len; /* buffer length */ + ns_msg handle; /* handle for response message */ + union { + HEADER hdr; + u_char buf[NS_PACKETSZ]; + } response; /* response buffers */ + + debug("Get AFSDB RR for cell name:'%s'", cell); + + /* query the dns for an AFSDB resource record */ + response_len = res_query(cell, + ns_c_in, + ns_t_afsdb, + response.buf, + sizeof(response)); + + if (response_len < 0) { + /* negative result */ + _nsError(h_errno, cell); + return -1; + } + + if (ns_initparse(response.buf, response_len, &handle) < 0) + error("ns_initparse: %m"); + + /* look up the hostnames we've obtained to get the actual addresses */ + afsdb_hosts_to_addrs(handle, ns_s_an); + + info("DNS query AFSDB RR results:%u ttl:%lu", payload_index, afs_ttl); + return 0; +} + +/* + * Look up an SRV record to get the VL server addresses [RFC 5864]. + */ +static int dns_query_VL_SRV(const char *cell) +{ + int response_len; /* buffer length */ + ns_msg handle; /* handle for response message */ + union { + HEADER hdr; + u_char buf[NS_PACKETSZ]; + } response; + char name[1024]; + + snprintf(name, sizeof(name), "_afs3-vlserver._udp.%s", cell); + + debug("Get VL SRV RR for name:'%s'", name); + + response_len = res_query(name, + ns_c_in, + ns_t_srv, + response.buf, + sizeof(response)); + + if (response_len < 0) { + /* negative result */ + _nsError(h_errno, cell); + return -1; + } + + if (ns_initparse(response.buf, response_len, &handle) < 0) + error("ns_initparse: %m"); + + /* look up the hostnames we've obtained to get the actual addresses */ + srv_hosts_to_addrs(handle, ns_s_an); + + info("DNS query VL SRV RR results:%u ttl:%lu", payload_index, afs_ttl); + return 0; +} + +/* + * Instantiate the key. + */ +static __attribute__((noreturn)) +void afs_instantiate(const char *cell) +{ + int ret; + + /* set the key's expiry time from the minimum TTL encountered */ + if (!debug_mode) { + ret = keyctl_set_timeout(key, afs_ttl); + if (ret == -1) + error("%s: keyctl_set_timeout: %m", __func__); + } + + /* handle a lack of results */ + if (payload_index == 0) + nsError(NO_DATA, cell); + + /* must include a NUL char at the end of the payload */ + payload[payload_index].iov_base = ""; + payload[payload_index++].iov_len = 1; + dump_payload(); + + /* load the key with data key */ + if (!debug_mode) { + ret = keyctl_instantiate_iov(key, payload, payload_index, 0); + if (ret == -1) + error("%s: keyctl_instantiate: %m", __func__); + } + + exit(0); +} + +/* + * Look up VL servers for AFS. + */ +void afs_look_up_VL_servers(const char *cell, char *options) +{ + /* Is the IP address family limited? */ + if (strcmp(options, "ipv4") == 0) + mask = INET_IP4_ONLY; + else if (strcmp(options, "ipv6") == 0) + mask = INET_IP6_ONLY; + + if (dns_query_VL_SRV(cell) != 0) + dns_query_AFSDB(cell); + + afs_instantiate(cell); +} diff --git a/key.dns.h b/key.dns.h new file mode 100644 index 0000000000..b143f4a411 --- /dev/null +++ b/key.dns.h @@ -0,0 +1,70 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public Licence as published by + * the Free Software Foundation; either version 2 of the Licence, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public Licence for more details. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_VLS 15 /* Max Volume Location Servers Per-Cell */ +#define INET_IP4_ONLY 0x1 +#define INET_IP6_ONLY 0x2 +#define INET_ALL 0xFF +#define ONE_ADDR_ONLY 0x100 + +/* + * key.dns_resolver.c + */ +extern key_serial_t key; +extern int debug_mode; +extern unsigned mask; + +#define N_PAYLOAD 256 +extern struct iovec payload[N_PAYLOAD]; +extern int payload_index; + +extern __attribute__((format(printf, 1, 2), noreturn)) +void error(const char *fmt, ...); +extern __attribute__((format(printf, 1, 2))) +void _error(const char *fmt, ...); +extern __attribute__((format(printf, 1, 2))) +void info(const char *fmt, ...); +extern __attribute__((noreturn)) +void nsError(int err, const char *domain); +extern void _nsError(int err, const char *domain); +extern __attribute__((format(printf, 1, 2))) +void debug(const char *fmt, ...); + +extern void append_address_to_payload(const char *addr); +extern void dump_payload(void); +extern int dns_resolver(const char *server_name, const char *port); + +/* + * dns.afsdb.c + */ +extern __attribute__((noreturn)) +void afs_look_up_VL_servers(const char *cell, char *options); diff --git a/key.dns_resolver.c b/key.dns_resolver.c new file mode 100644 index 0000000000..4ac27d3010 --- /dev/null +++ b/key.dns_resolver.c @@ -0,0 +1,565 @@ +/* + * DNS Resolver Module User-space Helper for AFSDB records + * + * Copyright (C) Wang Lei (wang840925@gmail.com) 2010 + * Authors: Wang Lei (wang840925@gmail.com) + * David Howells (dhowells@redhat.com) + * + * This is a userspace tool for querying AFSDB RR records in the DNS on behalf + * of the kernel, and converting the VL server addresses to IPv4 format so that + * they can be used by the kAFS filesystem. + * + * Compile with: + * + * cc -o key.dns_resolver key.dns_resolver.c -lresolv -lkeyutils + * + * As some function like res_init() should use the static library, which is a + * bug of libresolv, that is the reason for cifs.upcall to reimplement. + * + * To use this program, you must tell /sbin/request-key how to invoke it. You + * need to have the keyutils package installed and something like the following + * lines added to your /etc/request-key.conf file: + * + * #OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ... + * ====== ============ =========== ============ ========================== + * create dns_resolver afsdb:* * /sbin/key.dns_resolver %k + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "key.dns.h" + +static const char *DNS_PARSE_VERSION = "1.0"; +static const char prog[] = "key.dns_resolver"; +static const char key_type[] = "dns_resolver"; +static const char a_query_type[] = "a"; +static const char aaaa_query_type[] = "aaaa"; +static const char afsdb_query_type[] = "afsdb"; +key_serial_t key; +static int verbose; +int debug_mode; +unsigned mask = INET_ALL; + + +/* + * segmental payload + */ +struct iovec payload[N_PAYLOAD]; +int payload_index; + +/* + * Print an error to stderr or the syslog, negate the key being created and + * exit + */ +void error(const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + if (isatty(2)) { + vfprintf(stderr, fmt, va); + fputc('\n', stderr); + } else { + vsyslog(LOG_ERR, fmt, va); + } + va_end(va); + + /* + * on error, negatively instantiate the key ourselves so that we can + * make sure the kernel doesn't hang it off of a searchable keyring + * and interfere with the next attempt to instantiate the key. + */ + if (!debug_mode) + keyctl_negate(key, 1, KEY_REQKEY_DEFL_DEFAULT); + + exit(1); +} + +#define error(FMT, ...) error("Error: " FMT, ##__VA_ARGS__); + +/* + * Just print an error to stderr or the syslog + */ +void _error(const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + if (isatty(2)) { + vfprintf(stderr, fmt, va); + fputc('\n', stderr); + } else { + vsyslog(LOG_ERR, fmt, va); + } + va_end(va); +} + +/* + * Print status information + */ +void info(const char *fmt, ...) +{ + va_list va; + + if (verbose < 1) + return; + + va_start(va, fmt); + if (isatty(1)) { + fputs("I: ", stdout); + vfprintf(stdout, fmt, va); + fputc('\n', stdout); + } else { + vsyslog(LOG_INFO, fmt, va); + } + va_end(va); +} + +/* + * Print a nameserver error and exit + */ +static const int ns_errno_map[] = { + [0] = ECONNREFUSED, + [HOST_NOT_FOUND] = ENODATA, + [TRY_AGAIN] = EAGAIN, + [NO_RECOVERY] = ECONNREFUSED, + [NO_DATA] = ENODATA, +}; + +void _nsError(int err, const char *domain) +{ + if (isatty(2)) + fprintf(stderr, "NS:%s: %s.\n", domain, hstrerror(err)); + else + syslog(LOG_INFO, "%s: %s", domain, hstrerror(err)); + + if (err >= sizeof(ns_errno_map) / sizeof(ns_errno_map[0])) + err = ECONNREFUSED; + else + err = ns_errno_map[err]; + + info("Reject the key with error %d", err); +} + +void nsError(int err, const char *domain) +{ + unsigned timeout; + int ret; + + _nsError(err, domain); + + switch (err) { + case TRY_AGAIN: + timeout = 1; + break; + case 0: + case NO_RECOVERY: + timeout = 10; + break; + default: + timeout = 1 * 60; + break; + } + + if (!debug_mode) { + ret = keyctl_reject(key, timeout, err, KEY_REQKEY_DEFL_DEFAULT); + if (ret == -1) + error("%s: keyctl_reject: %m", __func__); + } + exit(0); +} + +/* + * Print debugging information + */ +void debug(const char *fmt, ...) +{ + va_list va; + + if (verbose < 2) + return; + + va_start(va, fmt); + if (isatty(1)) { + fputs("D: ", stdout); + vfprintf(stdout, fmt, va); + fputc('\n', stdout); + } else { + vsyslog(LOG_DEBUG, fmt, va); + } + va_end(va); +} + +/* + * Append an address to the payload segment list + */ +void append_address_to_payload(const char *addr) +{ + size_t sz = strlen(addr); + char *copy; + int loop; + + debug("append '%s'", addr); + + if (payload_index + 2 > N_PAYLOAD - 1) + return; + + /* discard duplicates */ + for (loop = 0; loop < payload_index; loop++) + if (payload[loop].iov_len == sz && + memcmp(payload[loop].iov_base, addr, sz) == 0) + return; + + copy = malloc(sz); + if (!copy) + error("%s: malloc: %m", __func__); + memcpy(copy, addr, sz); + + if (payload_index != 0) { + payload[payload_index ].iov_base = ","; + payload[payload_index++].iov_len = 1; + } + payload[payload_index ].iov_base = copy; + payload[payload_index++].iov_len = sz; +} + +/* + * Dump the payload when debugging + */ +void dump_payload(void) +{ + size_t plen, n; + char *buf, *p; + int loop; + + if (debug_mode) + verbose = 1; + if (verbose < 1) + return; + + plen = 0; + for (loop = 0; loop < payload_index; loop++) { + n = payload[loop].iov_len; + debug("seg[%d]: %zu", loop, n); + plen += n; + } + if (plen == 0) { + info("The key instantiation data is empty"); + return; + } + + debug("total: %zu", plen); + buf = malloc(plen + 1); + if (!buf) + return; + + p = buf; + for (loop = 0; loop < payload_index; loop++) { + n = payload[loop].iov_len; + memcpy(p, payload[loop].iov_base, n); + p += n; + } + + info("The key instantiation data is '%s'", buf); + free(buf); +} + +/* + * Perform address resolution on a hostname and add the resulting address as a + * string to the list of payload segments. + */ +int dns_resolver(const char *server_name, const char *port) +{ + struct addrinfo hints, *addr, *ai; + char buf[INET6_ADDRSTRLEN + 8 + 1]; + int ret, len; + void *sa; + + debug("Resolve '%s' with %x", server_name, mask); + + memset(&hints, 0, sizeof(hints)); + switch (mask & INET_ALL) { + case INET_IP4_ONLY: hints.ai_family = AF_INET; debug("IPv4"); break; + case INET_IP6_ONLY: hints.ai_family = AF_INET6; debug("IPv6"); break; + default: break; + } + + /* resolve name to ip */ + ret = getaddrinfo(server_name, NULL, &hints, &addr); + if (ret) { + info("unable to resolve hostname: %s [%s]", + server_name, gai_strerror(ret)); + return -1; + } + + for (ai = addr; ai; ai = ai->ai_next) { + debug("RR: %x,%x,%x,%x,%x,%s", + ai->ai_flags, ai->ai_family, + ai->ai_socktype, ai->ai_protocol, + ai->ai_addrlen, ai->ai_canonname); + + /* convert address to string */ + switch (ai->ai_family) { + case AF_INET: + if (!(mask & INET_IP4_ONLY)) + continue; + sa = &(((struct sockaddr_in *)ai->ai_addr)->sin_addr); + len = INET_ADDRSTRLEN; + break; + case AF_INET6: + if (!(mask & INET_IP6_ONLY)) + continue; + sa = &(((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr); + len = INET6_ADDRSTRLEN; + break; + default: + debug("Address of unknown family %u", addr->ai_family); + continue; + } + + if (!inet_ntop(ai->ai_family, sa, buf, len)) + error("%s: inet_ntop: %m", __func__); + + if (port) + strcat(buf, port); + append_address_to_payload(buf); + if (mask & ONE_ADDR_ONLY) + break; + } + + freeaddrinfo(addr); + return 0; +} + +/* + * Look up a A and/or AAAA records to get host addresses + * + * The callout_info is parsed for request options. For instance, "ipv4" to + * request only IPv4 addresses, "ipv6" to request only IPv6 addresses and + * "list" to get multiple addresses. + */ +static __attribute__((noreturn)) +int dns_query_a_or_aaaa(const char *hostname, char *options) +{ + int ret; + + debug("Get A/AAAA RR for hostname:'%s', options:'%s'", + hostname, options); + + if (!options[0]) { + /* legacy mode */ + mask = INET_IP4_ONLY | ONE_ADDR_ONLY; + } else { + char *k, *val; + + mask = INET_ALL | ONE_ADDR_ONLY; + + do { + k = options; + options = strchr(options, ' '); + if (!options) + options = k + strlen(k); + else + *options++ = '\0'; + if (!*k) + continue; + if (strchr(k, ',')) + error("Option name '%s' contains a comma", k); + + val = strchr(k, '='); + if (val) + *val++ = '\0'; + + debug("Opt %s", k); + + if (strcmp(k, "ipv4") == 0) { + mask &= ~INET_ALL; + mask |= INET_IP4_ONLY; + } else if (strcmp(k, "ipv6") == 0) { + mask &= ~INET_ALL; + mask |= INET_IP6_ONLY; + } else if (strcmp(k, "list") == 0) { + mask &= ~ONE_ADDR_ONLY; + } + + } while (*options); + } + + /* Turn the hostname into IP addresses */ + ret = dns_resolver(hostname, NULL); + if (ret) + nsError(NO_DATA, hostname); + + /* handle a lack of results */ + if (payload_index == 0) + nsError(NO_DATA, hostname); + + /* must include a NUL char at the end of the payload */ + payload[payload_index].iov_base = ""; + payload[payload_index++].iov_len = 1; + dump_payload(); + + /* load the key with data key */ + if (!debug_mode) { + ret = keyctl_instantiate_iov(key, payload, payload_index, 0); + if (ret == -1) + error("%s: keyctl_instantiate: %m", __func__); + } + + exit(0); +} + +/* + * Print usage details, + */ +static __attribute__((noreturn)) +void usage(void) +{ + if (isatty(2)) { + fprintf(stderr, + "Usage: %s [-vv] key_serial\n", + prog); + fprintf(stderr, + "Usage: %s -D [-vv] \n", + prog); + } else { + info("Usage: %s [-vv] key_serial", prog); + } + exit(2); +} + +const struct option long_options[] = { + { "debug", 0, NULL, 'D' }, + { "verbose", 0, NULL, 'v' }, + { "version", 0, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +/* + * + */ +int main(int argc, char *argv[]) +{ + int ktlen, qtlen, ret; + char *keyend, *p; + char *callout_info = NULL; + char *buf = NULL, *name; + + openlog(prog, 0, LOG_DAEMON); + + while ((ret = getopt_long(argc, argv, "vDV", long_options, NULL)) != -1) { + switch (ret) { + case 'D': + debug_mode = 1; + continue; + case 'V': + printf("version: %s from %s (%s)\n", + DNS_PARSE_VERSION, + keyutils_version_string, + keyutils_build_string); + exit(0); + case 'v': + verbose++; + continue; + default: + if (!isatty(2)) + syslog(LOG_ERR, "unknown option: %c", ret); + usage(); + } + } + + argc -= optind; + argv += optind; + + if (!debug_mode) { + if (argc != 1) + usage(); + + /* get the key ID */ + if (!**argv) + error("Invalid blank key ID"); + key = strtol(*argv, &p, 10); + if (*p) + error("Invalid key ID format"); + + /* get the key description (of the form "x;x;x;x;:") */ + ret = keyctl_describe_alloc(key, &buf); + if (ret == -1) + error("keyctl_describe_alloc failed: %m"); + + /* get the callout_info (which can supply options) */ + ret = keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, (void **)&callout_info); + if (ret == -1) + error("Invalid key callout_info read: %m"); + } else { + if (argc != 2) + usage(); + + ret = asprintf(&buf, "%s;-1;-1;0;%s", key_type, argv[0]); + if (ret < 0) + error("Error %m"); + callout_info = argv[1]; + } + + ret = 1; + info("Key description: '%s'", buf); + info("Callout info: '%s'", callout_info); + + p = strchr(buf, ';'); + if (!p) + error("Badly formatted key description '%s'", buf); + ktlen = p - buf; + + /* make sure it's the type we are expecting */ + if (ktlen != sizeof(key_type) - 1 || + memcmp(buf, key_type, ktlen) != 0) + error("Key type is not supported: '%*.*s'", ktlen, ktlen, buf); + + keyend = buf + ktlen + 1; + + /* the actual key description follows the last semicolon */ + keyend = rindex(keyend, ';'); + if (!keyend) + error("Invalid key description: %s", buf); + keyend++; + + name = index(keyend, ':'); + if (!name) + dns_query_a_or_aaaa(keyend, callout_info); + + qtlen = name - keyend; + name++; + + info("Query type: '%*.*s'", qtlen, qtlen, keyend); + + if ((qtlen == sizeof(a_query_type) - 1 && + memcmp(keyend, a_query_type, sizeof(a_query_type) - 1) == 0) || + (qtlen == sizeof(aaaa_query_type) - 1 && + memcmp(keyend, aaaa_query_type, sizeof(aaaa_query_type) - 1) == 0) + ) { + info("Do DNS query of A/AAAA type for:'%s' mask:'%s'", + name, callout_info); + dns_query_a_or_aaaa(name, callout_info); + } + + if (qtlen == sizeof(afsdb_query_type) - 1 && + memcmp(keyend, afsdb_query_type, sizeof(afsdb_query_type) - 1) == 0 + ) { + info("Do AFS VL server query for:'%s' mask:'%s'", + name, callout_info); + afs_look_up_VL_servers(name, callout_info); + } + + error("Query type: \"%*.*s\" is not supported", qtlen, qtlen, keyend); +} diff --git a/keyctl.c b/keyctl.c new file mode 100644 index 0000000000..4c5d91c65b --- /dev/null +++ b/keyctl.c @@ -0,0 +1,2375 @@ +/* keyctl.c: key control program + * + * Copyright (C) 2005, 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "keyutils.h" +#include + +struct command { + void (*action)(int argc, char *argv[]) __attribute__((noreturn)); + const char *name; + const char *format; +}; + +#define nr __attribute__((noreturn)) + +static nr void act_keyctl___version(int argc, char *argv[]); +static nr void act_keyctl_show(int argc, char *argv[]); +static nr void act_keyctl_add(int argc, char *argv[]); +static nr void act_keyctl_padd(int argc, char *argv[]); +static nr void act_keyctl_request(int argc, char *argv[]); +static nr void act_keyctl_request2(int argc, char *argv[]); +static nr void act_keyctl_prequest2(int argc, char *argv[]); +static nr void act_keyctl_update(int argc, char *argv[]); +static nr void act_keyctl_pupdate(int argc, char *argv[]); +static nr void act_keyctl_newring(int argc, char *argv[]); +static nr void act_keyctl_revoke(int argc, char *argv[]); +static nr void act_keyctl_clear(int argc, char *argv[]); +static nr void act_keyctl_link(int argc, char *argv[]); +static nr void act_keyctl_unlink(int argc, char *argv[]); +static nr void act_keyctl_search(int argc, char *argv[]); +static nr void act_keyctl_read(int argc, char *argv[]); +static nr void act_keyctl_pipe(int argc, char *argv[]); +static nr void act_keyctl_print(int argc, char *argv[]); +static nr void act_keyctl_list(int argc, char *argv[]); +static nr void act_keyctl_rlist(int argc, char *argv[]); +static nr void act_keyctl_describe(int argc, char *argv[]); +static nr void act_keyctl_rdescribe(int argc, char *argv[]); +static nr void act_keyctl_chown(int argc, char *argv[]); +static nr void act_keyctl_chgrp(int argc, char *argv[]); +static nr void act_keyctl_setperm(int argc, char *argv[]); +static nr void act_keyctl_session(int argc, char *argv[]); +static nr void act_keyctl_instantiate(int argc, char *argv[]); +static nr void act_keyctl_pinstantiate(int argc, char *argv[]); +static nr void act_keyctl_negate(int argc, char *argv[]); +static nr void act_keyctl_timeout(int argc, char *argv[]); +static nr void act_keyctl_security(int argc, char *argv[]); +static nr void act_keyctl_new_session(int argc, char *argv[]); +static nr void act_keyctl_reject(int argc, char *argv[]); +static nr void act_keyctl_reap(int argc, char *argv[]); +static nr void act_keyctl_purge(int argc, char *argv[]); +static nr void act_keyctl_invalidate(int argc, char *argv[]); +static nr void act_keyctl_get_persistent(int argc, char *argv[]); +static nr void act_keyctl_dh_compute(int argc, char *argv[]); +static nr void act_keyctl_dh_compute_kdf(int argc, char *argv[]); +static nr void act_keyctl_dh_compute_kdf_oi(int argc, char *argv[]); +static nr void act_keyctl_restrict_keyring(int argc, char *argv[]); +static nr void act_keyctl_pkey_query(int argc, char *argv[]); +static nr void act_keyctl_pkey_encrypt(int argc, char *argv[]); +static nr void act_keyctl_pkey_decrypt(int argc, char *argv[]); +static nr void act_keyctl_pkey_sign(int argc, char *argv[]); +static nr void act_keyctl_pkey_verify(int argc, char *argv[]); +static nr void act_keyctl_move(int argc, char *argv[]); +static nr void act_keyctl_supports(int argc, char *argv[]); + +const struct command commands[] = { + { act_keyctl___version, "--version", "" }, + { act_keyctl_add, "add", " " }, + { act_keyctl_chgrp, "chgrp", " " }, + { act_keyctl_chown, "chown", " " }, + { act_keyctl_clear, "clear", "" }, + { act_keyctl_describe, "describe", "" }, + { act_keyctl_dh_compute, "dh_compute", " " }, + { act_keyctl_dh_compute_kdf, "dh_compute_kdf", " " }, + { act_keyctl_dh_compute_kdf_oi, "dh_compute_kdf_oi", " " }, + { act_keyctl_instantiate, "instantiate"," " }, + { act_keyctl_invalidate,"invalidate", "" }, + { act_keyctl_get_persistent, "get_persistent", " []" }, + { act_keyctl_link, "link", " " }, + { act_keyctl_list, "list", "" }, + { act_keyctl_move, "move", "[-f] " }, + { act_keyctl_negate, "negate", " " }, + { act_keyctl_new_session, "new_session", "" }, + { act_keyctl_newring, "newring", " " }, + { act_keyctl_padd, "padd", " " }, + { act_keyctl_pinstantiate, "pinstantiate"," " }, + { act_keyctl_pipe, "pipe", "" }, + { act_keyctl_pkey_query, "pkey_query", " [k=v]*" }, + { act_keyctl_pkey_encrypt, "pkey_encrypt", " [k=v]*" }, + { act_keyctl_pkey_decrypt, "pkey_decrypt", " [k=v]*" }, + { act_keyctl_pkey_sign, "pkey_sign", " [k=v]*" }, + { act_keyctl_pkey_verify, "pkey_verify", " [k=v]*" }, + { act_keyctl_prequest2, "prequest2", " []" }, + { act_keyctl_print, "print", "" }, + { act_keyctl_pupdate, "pupdate", "" }, + { act_keyctl_purge, "purge", "" }, + { NULL, "purge", "[-p] [-i] " }, + { NULL, "purge", "-s " }, + { act_keyctl_rdescribe, "rdescribe", " [sep]" }, + { act_keyctl_read, "read", "" }, + { act_keyctl_reap, "reap", "[-v]" }, + { act_keyctl_reject, "reject", " " }, + { act_keyctl_request, "request", " []" }, + { act_keyctl_request2, "request2", " []" }, + { act_keyctl_restrict_keyring, "restrict_keyring", " [ []]" }, + { act_keyctl_revoke, "revoke", "" }, + { act_keyctl_rlist, "rlist", "" }, + { act_keyctl_search, "search", " []" }, + { act_keyctl_security, "security", "" }, + { act_keyctl_session, "session", "" }, + { NULL, "session", "- [ ...]" }, + { NULL, "session", " [ ...]" }, + { act_keyctl_setperm, "setperm", " " }, + { act_keyctl_show, "show", "[-x] []" }, + { act_keyctl_supports, "supports", "[]" }, + { act_keyctl_timeout, "timeout", " " }, + { act_keyctl_unlink, "unlink", " []" }, + { act_keyctl_update, "update", " " }, + { NULL, NULL, NULL } +}; + +static int dump_key_tree(key_serial_t keyring, const char *name, int hex_key_IDs); +static void format(void) __attribute__((noreturn)); +static void error(const char *msg) __attribute__((noreturn)); +static key_serial_t get_key_id(char *arg); +static void *read_file(const char *name, size_t *_size); + +static uid_t myuid; +static gid_t mygid, *mygroups; +static int myngroups; +static int verbose; + +/*****************************************************************************/ +/* + * handle an error + */ +static inline void error(const char *msg) +{ + perror(msg); + exit(1); + +} /* end error() */ + +/*****************************************************************************/ +/* + * execute the appropriate subcommand + */ +int main(int argc, char *argv[]) +{ + const struct command *cmd, *best; + int n; + + argv++; + argc--; + + if (argc == 0) + format(); + + /* find the best fit command */ + best = NULL; + n = strlen(*argv); + + for (cmd = commands; cmd->name; cmd++) { + if (!cmd->action) + continue; + if (strlen(cmd->name) > n) + continue; + if (memcmp(cmd->name, *argv, n) != 0) + continue; + + if (cmd->name[n] == 0) { + /* exact match */ + best = cmd; + break; + } + + /* partial match */ + if (best) { + fprintf(stderr, "Ambiguous command\n"); + exit(2); + } + + best = cmd; + } + + if (!best) { + fprintf(stderr, "Unknown command\n"); + exit(2); + } + + best->action(argc, argv); + +} /* end main() */ + +/*****************************************************************************/ +/* + * display command format information + */ +static void format(void) +{ + const struct command *cmd; + + fprintf(stderr, "Format:\n"); + + for (cmd = commands; cmd->name; cmd++) + fprintf(stderr, " keyctl %s %s\n", cmd->name, cmd->format); + + fprintf(stderr, "\n"); + fprintf(stderr, "Key/keyring ID:\n"); + fprintf(stderr, " numeric keyring ID\n"); + fprintf(stderr, " @t thread keyring\n"); + fprintf(stderr, " @p process keyring\n"); + fprintf(stderr, " @s session keyring\n"); + fprintf(stderr, " @u user keyring\n"); + fprintf(stderr, " @us user default session keyring\n"); + fprintf(stderr, " @g group keyring\n"); + fprintf(stderr, " @a assumed request_key authorisation key\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " can be \"user\" for a user-defined keyring\n"); + fprintf(stderr, "If you do this, prefix the description with \":\"\n"); + + exit(2); + +} /* end format() */ + +/*****************************************************************************/ +/* + * Display version information + */ +static void act_keyctl___version(int argc, char *argv[]) +{ + printf("keyctl from %s (Built %s)\n", + keyutils_version_string, keyutils_build_string); + exit(0); +} + +/*****************************************************************************/ +/* + * grab data from stdin + */ +static char *grab_stdin(size_t *_size) +{ + static char input[1024 * 1024 + 1]; + int n, tmp; + + n = 0; + do { + tmp = read(0, input + n, sizeof(input) - 1 - n); + if (tmp < 0) + error("stdin"); + + if (tmp == 0) + break; + + n += tmp; + + } while (n < sizeof(input)); + + if (n >= sizeof(input)) { + fprintf(stderr, "Too much data read on stdin\n"); + exit(1); + } + + input[n] = '\0'; + *_size = n; + + return input; + +} /* end grab_stdin() */ + +/* + * Load the groups list and grab the process's UID and GID. + */ +static void grab_creds(void) +{ + static int inited; + + if (inited) + return; + inited = 1; + + /* grab my UID, GID and groups */ + myuid = geteuid(); + mygid = getegid(); + myngroups = getgroups(0, NULL); + + if (myuid == -1 || mygid == -1 || myngroups == -1) + error("Unable to get UID/GID/#Groups\n"); + + mygroups = calloc(myngroups, sizeof(gid_t)); + if (!mygroups) + error("calloc"); + + myngroups = getgroups(myngroups, mygroups); + if (myngroups < 0) + error("Unable to get Groups\n"); +} + +/*****************************************************************************/ +/* + * convert the permissions mask to a string representing the permissions we + * have actually been granted + */ +static void calc_perms(char *pretty, key_perm_t perm, uid_t uid, gid_t gid) +{ + unsigned perms; + gid_t *pg; + int loop; + + grab_creds(); + + perms = (perm & KEY_POS_ALL) >> 24; + + if (uid == myuid) { + perms |= (perm & KEY_USR_ALL) >> 16; + goto write_mask; + } + + if (gid != -1) { + if (gid == mygid) { + perms |= (perm & KEY_GRP_ALL) >> 8; + goto write_mask; + } + + pg = mygroups; + for (loop = myngroups; loop > 0; loop--, pg++) { + if (gid == *pg) { + perms |= (perm & KEY_GRP_ALL) >> 8; + goto write_mask; + } + } + } + + perms |= (perm & KEY_OTH_ALL); + +write_mask: + sprintf(pretty, "--%c%c%c%c%c%c", + perms & KEY_OTH_SETATTR ? 'a' : '-', + perms & KEY_OTH_LINK ? 'l' : '-', + perms & KEY_OTH_SEARCH ? 's' : '-', + perms & KEY_OTH_WRITE ? 'w' : '-', + perms & KEY_OTH_READ ? 'r' : '-', + perms & KEY_OTH_VIEW ? 'v' : '-'); + +} /* end calc_perms() */ + +/*****************************************************************************/ +/* + * show the parent process's session keyring + */ +static void act_keyctl_show(int argc, char *argv[]) +{ + key_serial_t keyring = KEY_SPEC_SESSION_KEYRING; + int hex_key_IDs = 0; + + if (argc >= 2 && strcmp(argv[1], "-x") == 0) { + hex_key_IDs = 1; + argc--; + argv++; + } + + if (argc > 2) + format(); + + if (argc == 2) + keyring = get_key_id(argv[1]); + + dump_key_tree(keyring, argc == 2 ? "Keyring" : "Session Keyring", hex_key_IDs); + exit(0); + +} /* end act_keyctl_show() */ + +/*****************************************************************************/ +/* + * add a key + */ +static void act_keyctl_add(int argc, char *argv[]) +{ + key_serial_t dest; + int ret; + + if (argc != 5) + format(); + + dest = get_key_id(argv[4]); + + ret = add_key(argv[1], argv[2], argv[3], strlen(argv[3]), dest); + if (ret < 0) + error("add_key"); + + /* print the resulting key ID */ + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_add() */ + +/*****************************************************************************/ +/* + * add a key, reading from a pipe + */ +static void act_keyctl_padd(int argc, char *argv[]) +{ + key_serial_t dest; + size_t datalen; + void *data; + int ret; + + + if (argc != 4) + format(); + + dest = get_key_id(argv[3]); + + data = grab_stdin(&datalen); + + ret = add_key(argv[1], argv[2], data, datalen, dest); + if (ret < 0) + error("add_key"); + + /* print the resulting key ID */ + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_padd() */ + +/*****************************************************************************/ +/* + * request a key + */ +static void act_keyctl_request(int argc, char *argv[]) +{ + key_serial_t dest; + int ret; + + if (argc != 3 && argc != 4) + format(); + + dest = 0; + if (argc == 4) + dest = get_key_id(argv[3]); + + ret = request_key(argv[1], argv[2], NULL, dest); + if (ret < 0) + error("request_key"); + + /* print the resulting key ID */ + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_request() */ + +/*****************************************************************************/ +/* + * request a key, with recourse to /sbin/request-key + */ +static void act_keyctl_request2(int argc, char *argv[]) +{ + key_serial_t dest; + int ret; + + if (argc != 4 && argc != 5) + format(); + + dest = 0; + if (argc == 5) + dest = get_key_id(argv[4]); + + ret = request_key(argv[1], argv[2], argv[3], dest); + if (ret < 0) + error("request_key"); + + /* print the resulting key ID */ + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_request2() */ + +/*****************************************************************************/ +/* + * request a key, with recourse to /sbin/request-key, reading the callout info + * from a pipe + */ +static void act_keyctl_prequest2(int argc, char *argv[]) +{ + char *args[6]; + size_t datalen; + + if (argc != 3 && argc != 4) + format(); + + args[0] = argv[0]; + args[1] = argv[1]; + args[2] = argv[2]; + args[3] = grab_stdin(&datalen); + args[4] = argv[3]; + args[5] = NULL; + + act_keyctl_request2(argc + 1, args); + +} /* end act_keyctl_prequest2() */ + +/*****************************************************************************/ +/* + * update a key + */ +static void act_keyctl_update(int argc, char *argv[]) +{ + key_serial_t key; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + + if (keyctl_update(key, argv[2], strlen(argv[2])) < 0) + error("keyctl_update"); + + exit(0); + +} /* end act_keyctl_update() */ + +/*****************************************************************************/ +/* + * update a key, reading from a pipe + */ +static void act_keyctl_pupdate(int argc, char *argv[]) +{ + key_serial_t key; + size_t datalen; + void *data; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + data = grab_stdin(&datalen); + + if (keyctl_update(key, data, datalen) < 0) + error("keyctl_update"); + + exit(0); + +} /* end act_keyctl_pupdate() */ + +/*****************************************************************************/ +/* + * create a new keyring + */ +static void act_keyctl_newring(int argc, char *argv[]) +{ + key_serial_t dest; + int ret; + + if (argc != 3) + format(); + + dest = get_key_id(argv[2]); + + ret = add_key("keyring", argv[1], NULL, 0, dest); + if (ret < 0) + error("add_key"); + + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_newring() */ + +/*****************************************************************************/ +/* + * revoke a key + */ +static void act_keyctl_revoke(int argc, char *argv[]) +{ + key_serial_t key; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + if (keyctl_revoke(key) < 0) + error("keyctl_revoke"); + + exit(0); + +} /* end act_keyctl_revoke() */ + +/*****************************************************************************/ +/* + * clear a keyring + */ +static void act_keyctl_clear(int argc, char *argv[]) +{ + key_serial_t keyring; + + if (argc != 2) + format(); + + keyring = get_key_id(argv[1]); + + if (keyctl_clear(keyring) < 0) + error("keyctl_clear"); + + exit(0); + +} /* end act_keyctl_clear() */ + +/*****************************************************************************/ +/* + * link a key to a keyring + */ +static void act_keyctl_link(int argc, char *argv[]) +{ + key_serial_t keyring, key; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + keyring = get_key_id(argv[2]); + + if (keyctl_link(key, keyring) < 0) + error("keyctl_link"); + + exit(0); + +} /* end act_keyctl_link() */ + +/* + * Attempt to unlink a key matching the ID + */ +static int act_keyctl_unlink_func(key_serial_t parent, key_serial_t key, + char *desc, int desc_len, void *data) +{ + key_serial_t *target = data; + + if (key == *target) + return keyctl_unlink(key, parent) < 0 ? 0 : 1; + return 0; +} + +/* + * Unlink a key from a keyring or from the session keyring tree. + */ +static void act_keyctl_unlink(int argc, char *argv[]) +{ + key_serial_t keyring, key; + int n; + + if (argc != 2 && argc != 3) + format(); + + key = get_key_id(argv[1]); + + if (argc == 3) { + keyring = get_key_id(argv[2]); + if (keyctl_unlink(key, keyring) < 0) + error("keyctl_unlink"); + } else { + n = recursive_session_key_scan(act_keyctl_unlink_func, &key); + printf("%d links removed\n", n); + } + + exit(0); +} + +/*****************************************************************************/ +/* + * search a keyring for a key + */ +static void act_keyctl_search(int argc, char *argv[]) +{ + key_serial_t keyring, dest; + int ret; + + if (argc != 4 && argc != 5) + format(); + + keyring = get_key_id(argv[1]); + + dest = 0; + if (argc == 5) + dest = get_key_id(argv[4]); + + ret = keyctl_search(keyring, argv[2], argv[3], dest); + if (ret < 0) + error("keyctl_search"); + + /* print the ID of the key we found */ + printf("%d\n", ret); + exit(0); + +} /* end act_keyctl_search() */ + +/*****************************************************************************/ +/* + * read a key + */ +static void act_keyctl_read(int argc, char *argv[]) +{ + key_serial_t key; + void *buffer; + char *p; + int ret, sep, col; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + /* read the key payload data */ + ret = keyctl_read_alloc(key, &buffer); + if (ret < 0) + error("keyctl_read_alloc"); + + if (ret == 0) { + printf("No data in key\n"); + exit(0); + } + + /* hexdump the contents */ + printf("%u bytes of data in key:\n", ret); + + sep = 0; + col = 0; + p = buffer; + + do { + if (sep) { + putchar(sep); + sep = 0; + } + + printf("%02hhx", *p); + p++; + + col++; + if (col % 32 == 0) + sep = '\n'; + else if (col % 4 == 0) + sep = ' '; + + } while (--ret > 0); + + printf("\n"); + exit(0); + +} /* end act_keyctl_read() */ + +/*****************************************************************************/ +/* + * read a key and dump raw to stdout + */ +static void act_keyctl_pipe(int argc, char *argv[]) +{ + key_serial_t key; + void *buffer; + int ret; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + /* read the key payload data */ + ret = keyctl_read_alloc(key, &buffer); + if (ret < 0) + error("keyctl_read_alloc"); + + if (ret > 0 && write(1, buffer, ret) < 0) + error("write"); + exit(0); + +} /* end act_keyctl_pipe() */ + +/*****************************************************************************/ +/* + * read a key and dump to stdout in printable form + */ +static void act_keyctl_print(int argc, char *argv[]) +{ + key_serial_t key; + void *buffer; + char *p; + int loop, ret; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + /* read the key payload data */ + ret = keyctl_read_alloc(key, &buffer); + if (ret < 0) + error("keyctl_read_alloc"); + + /* see if it's printable */ + p = buffer; + for (loop = ret; loop > 0; loop--, p++) + if (!isprint(*p)) + goto not_printable; + + /* it is */ + printf("%s\n", (char *) buffer); + exit(0); + +not_printable: + /* it isn't */ + printf(":hex:"); + p = buffer; + for (loop = ret; loop > 0; loop--, p++) + printf("%02hhx", *p); + printf("\n"); + exit(0); + +} /* end act_keyctl_print() */ + +/*****************************************************************************/ +/* + * list a keyring + */ +static void act_keyctl_list(int argc, char *argv[]) +{ + key_serial_t keyring, key, *pk; + key_perm_t perm; + void *keylist; + char *buffer, pretty_mask[9]; + uid_t uid; + gid_t gid; + int count, tlen, dpos, n, ret; + + if (argc != 2) + format(); + + keyring = get_key_id(argv[1]); + + /* read the key payload data */ + count = keyctl_read_alloc(keyring, &keylist); + if (count < 0) + error("keyctl_read_alloc"); + + count /= sizeof(key_serial_t); + + if (count == 0) { + printf("keyring is empty\n"); + exit(0); + } + + /* list the keys in the keyring */ + if (count == 1) + printf("1 key in keyring:\n"); + else + printf("%u keys in keyring:\n", count); + + pk = keylist; + do { + key = *pk++; + + ret = keyctl_describe_alloc(key, &buffer); + if (ret < 0) { + printf("%9d: key inaccessible (%m)\n", key); + continue; + } + + uid = 0; + gid = 0; + perm = 0; + + tlen = -1; + dpos = -1; + + n = sscanf((char *) buffer, "%*[^;]%n;%d;%d;%x;%n", + &tlen, &uid, &gid, &perm, &dpos); + if (n != 3) { + fprintf(stderr, "Unparseable description obtained for key %d\n", key); + exit(3); + } + + calc_perms(pretty_mask, perm, uid, gid); + + printf("%9d: %s %5d %5d %*.*s: %s\n", + key, + pretty_mask, + uid, gid, + tlen, tlen, buffer, + buffer + dpos); + + free(buffer); + + } while (--count); + + exit(0); + +} /* end act_keyctl_list() */ + +/*****************************************************************************/ +/* + * produce a raw list of a keyring + */ +static void act_keyctl_rlist(int argc, char *argv[]) +{ + key_serial_t keyring, key, *pk; + void *keylist; + int count; + + if (argc != 2) + format(); + + keyring = get_key_id(argv[1]); + + /* read the key payload data */ + count = keyctl_read_alloc(keyring, &keylist); + if (count < 0) + error("keyctl_read_alloc"); + + count /= sizeof(key_serial_t); + + /* list the keys in the keyring */ + if (count <= 0) { + printf("\n"); + } + else { + pk = keylist; + for (; count > 0; count--) { + key = *pk++; + printf("%d%c", key, count == 1 ? '\n' : ' '); + } + } + + exit(0); + +} /* end act_keyctl_rlist() */ + +/*****************************************************************************/ +/* + * describe a key + */ +static void act_keyctl_describe(int argc, char *argv[]) +{ + key_serial_t key; + key_perm_t perm; + char *buffer; + uid_t uid; + gid_t gid; + int tlen, dpos, n, ret; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + /* get key description */ + ret = keyctl_describe_alloc(key, &buffer); + if (ret < 0) + error("keyctl_describe_alloc"); + + /* parse it */ + uid = 0; + gid = 0; + perm = 0; + + tlen = -1; + dpos = -1; + + n = sscanf(buffer, "%*[^;]%n;%d;%d;%x;%n", + &tlen, &uid, &gid, &perm, &dpos); + if (n != 3) { + fprintf(stderr, "Unparseable description obtained for key %d\n", key); + exit(3); + } + + /* display it */ + printf("%9d:" + " %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c" + " %5d %5d %*.*s: %s\n", + key, + perm & KEY_POS_SETATTR ? 'a' : '-', + perm & KEY_POS_LINK ? 'l' : '-', + perm & KEY_POS_SEARCH ? 's' : '-', + perm & KEY_POS_WRITE ? 'w' : '-', + perm & KEY_POS_READ ? 'r' : '-', + perm & KEY_POS_VIEW ? 'v' : '-', + + perm & KEY_USR_SETATTR ? 'a' : '-', + perm & KEY_USR_LINK ? 'l' : '-', + perm & KEY_USR_SEARCH ? 's' : '-', + perm & KEY_USR_WRITE ? 'w' : '-', + perm & KEY_USR_READ ? 'r' : '-', + perm & KEY_USR_VIEW ? 'v' : '-', + + perm & KEY_GRP_SETATTR ? 'a' : '-', + perm & KEY_GRP_LINK ? 'l' : '-', + perm & KEY_GRP_SEARCH ? 's' : '-', + perm & KEY_GRP_WRITE ? 'w' : '-', + perm & KEY_GRP_READ ? 'r' : '-', + perm & KEY_GRP_VIEW ? 'v' : '-', + + perm & KEY_OTH_SETATTR ? 'a' : '-', + perm & KEY_OTH_LINK ? 'l' : '-', + perm & KEY_OTH_SEARCH ? 's' : '-', + perm & KEY_OTH_WRITE ? 'w' : '-', + perm & KEY_OTH_READ ? 'r' : '-', + perm & KEY_OTH_VIEW ? 'v' : '-', + uid, gid, + tlen, tlen, buffer, + buffer + dpos); + + exit(0); + +} /* end act_keyctl_describe() */ + +/*****************************************************************************/ +/* + * get raw key description + */ +static void act_keyctl_rdescribe(int argc, char *argv[]) +{ + key_serial_t key; + char *buffer, *q; + int ret; + + if (argc != 2 && argc != 3) + format(); + if (argc == 3 && !argv[2][0]) + format(); + + key = get_key_id(argv[1]); + + /* get key description */ + ret = keyctl_describe_alloc(key, &buffer); + if (ret < 0) + error("keyctl_describe"); + + /* replace semicolon separators with requested alternative */ + if (argc == 3) { + for (q = buffer; *q; q++) + if (*q == ';') + *q = argv[2][0]; + } + + /* display raw description */ + printf("%s\n", buffer); + exit(0); + +} /* end act_keyctl_rdescribe() */ + +/*****************************************************************************/ +/* + * change a key's ownership + */ +static void act_keyctl_chown(int argc, char *argv[]) +{ + key_serial_t key; + uid_t uid; + char *q; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + + uid = strtoul(argv[2], &q, 0); + if (*q) { + fprintf(stderr, "Unparsable uid: '%s'\n", argv[2]); + exit(2); + } + + if (keyctl_chown(key, uid, -1) < 0) + error("keyctl_chown"); + + exit(0); + +} /* end act_keyctl_chown() */ + +/*****************************************************************************/ +/* + * change a key's group ownership + */ +static void act_keyctl_chgrp(int argc, char *argv[]) +{ + key_serial_t key; + gid_t gid; + char *q; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + + gid = strtoul(argv[2], &q, 0); + if (*q) { + fprintf(stderr, "Unparsable gid: '%s'\n", argv[2]); + exit(2); + } + + if (keyctl_chown(key, -1, gid) < 0) + error("keyctl_chown"); + + exit(0); + +} /* end act_keyctl_chgrp() */ + +/*****************************************************************************/ +/* + * set the permissions on a key + */ +static void act_keyctl_setperm(int argc, char *argv[]) +{ + key_serial_t key; + key_perm_t perm; + char *q; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + perm = strtoul(argv[2], &q, 0); + if (*q) { + fprintf(stderr, "Unparsable permissions: '%s'\n", argv[2]); + exit(2); + } + + if (keyctl_setperm(key, perm) < 0) + error("keyctl_setperm"); + + exit(0); + +} /* end act_keyctl_setperm() */ + +/*****************************************************************************/ +/* + * start a process in a new session + */ +static void act_keyctl_session(int argc, char *argv[]) +{ + char *p, *q; + int ret; + + argv++; + argc--; + + /* no extra arguments signifies a standard shell in an anonymous + * session */ + p = NULL; + if (argc != 0) { + /* a dash signifies an anonymous session */ + p = *argv; + if (strcmp(p, "-") == 0) + p = NULL; + + argv++; + argc--; + } + + /* create a new session keyring */ + ret = keyctl_join_session_keyring(p); + if (ret < 0) + error("keyctl_join_session_keyring"); + + fprintf(stderr, "Joined session keyring: %d\n", ret); + + /* run the standard shell if no arguments */ + if (argc == 0) { + q = getenv("SHELL"); + if (!q) + q = "/bin/sh"; + execl(q, q, NULL); + error(q); + } + + /* run the command specified */ + execvp(argv[0], argv); + error(argv[0]); + +} /* end act_keyctl_session() */ + +/*****************************************************************************/ +/* + * instantiate a key that's under construction + */ +static void act_keyctl_instantiate(int argc, char *argv[]) +{ + key_serial_t key, dest; + + if (argc != 4) + format(); + + key = get_key_id(argv[1]); + dest = get_key_id(argv[3]); + + if (keyctl_instantiate(key, argv[2], strlen(argv[2]), dest) < 0) + error("keyctl_instantiate"); + + exit(0); + +} /* end act_keyctl_instantiate() */ + +/*****************************************************************************/ +/* + * instantiate a key, reading from a pipe + */ +static void act_keyctl_pinstantiate(int argc, char *argv[]) +{ + key_serial_t key, dest; + size_t datalen; + void *data; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + dest = get_key_id(argv[2]); + data = grab_stdin(&datalen); + + if (keyctl_instantiate(key, data, datalen, dest) < 0) + error("keyctl_instantiate"); + + exit(0); + +} /* end act_keyctl_pinstantiate() */ + +/*****************************************************************************/ +/* + * negate a key that's under construction + */ +static void act_keyctl_negate(int argc, char *argv[]) +{ + unsigned long timeout; + key_serial_t key, dest; + char *q; + + if (argc != 4) + format(); + + key = get_key_id(argv[1]); + + timeout = strtoul(argv[2], &q, 10); + if (*q) { + fprintf(stderr, "Unparsable timeout: '%s'\n", argv[2]); + exit(2); + } + + dest = get_key_id(argv[3]); + + if (keyctl_negate(key, timeout, dest) < 0) + error("keyctl_negate"); + + exit(0); + +} /* end act_keyctl_negate() */ + +/*****************************************************************************/ +/* + * set a key's timeout + */ +static void act_keyctl_timeout(int argc, char *argv[]) +{ + unsigned long timeout; + key_serial_t key; + char *q; + + if (argc != 3) + format(); + + key = get_key_id(argv[1]); + + timeout = strtoul(argv[2], &q, 10); + if (*q) { + fprintf(stderr, "Unparsable timeout: '%s'\n", argv[2]); + exit(2); + } + + if (keyctl_set_timeout(key, timeout) < 0) + error("keyctl_set_timeout"); + + exit(0); + +} /* end act_keyctl_timeout() */ + +/*****************************************************************************/ +/* + * get a key's security label + */ +static void act_keyctl_security(int argc, char *argv[]) +{ + key_serial_t key; + char *buffer; + int ret; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + /* get key description */ + ret = keyctl_get_security_alloc(key, &buffer); + if (ret < 0) + error("keyctl_getsecurity"); + + printf("%s\n", buffer); + exit(0); +} + +/*****************************************************************************/ +/* + * install a new session keyring on the parent process + */ +static void act_keyctl_new_session(int argc, char *argv[]) +{ + key_serial_t keyring; + + if (argc != 1) + format(); + + if (keyctl_join_session_keyring(NULL) < 0) + error("keyctl_join_session_keyring"); + + if (keyctl_session_to_parent() < 0) + error("keyctl_session_to_parent"); + + keyring = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); + if (keyring < 0) + error("keyctl_get_keyring_ID"); + + /* print the resulting key ID */ + printf("%d\n", keyring); + exit(0); +} + +/*****************************************************************************/ +/* + * reject a key that's under construction + */ +static void act_keyctl_reject(int argc, char *argv[]) +{ + unsigned long timeout; + key_serial_t key, dest; + unsigned long rejerr; + char *q; + + if (argc != 5) + format(); + + key = get_key_id(argv[1]); + + timeout = strtoul(argv[2], &q, 10); + if (*q) { + fprintf(stderr, "Unparsable timeout: '%s'\n", argv[2]); + exit(2); + } + + if (strcmp(argv[3], "rejected") == 0) { + rejerr = EKEYREJECTED; + } else if (strcmp(argv[3], "revoked") == 0) { + rejerr = EKEYREVOKED; + } else if (strcmp(argv[3], "expired") == 0) { + rejerr = EKEYEXPIRED; + } else { + rejerr = strtoul(argv[3], &q, 10); + if (*q) { + fprintf(stderr, "Unparsable error: '%s'\n", argv[3]); + exit(2); + } + } + + dest = get_key_id(argv[4]); + + if (keyctl_reject(key, timeout, rejerr, dest) < 0) + error("keyctl_negate"); + + exit(0); +} + +/* + * Attempt to unlink a key if we can't read it for reasons other than we don't + * have permission + */ +static int act_keyctl_reap_func(key_serial_t parent, key_serial_t key, + char *desc, int desc_len, void *data) +{ + if (desc_len < 0 && errno != EACCES) { + if (verbose) + printf("Reap %d", key); + if (keyctl_unlink(key, parent) < 0) { + if (verbose) + printf("... failed %m\n"); + return 0; + } else { + if (verbose) + printf("\n"); + return 1; + }; + } + return 0; +} + +/* + * Reap the dead keys from the session keyring tree + */ +static void act_keyctl_reap(int argc, char *argv[]) +{ + int n; + + if (argc > 1 && strcmp(argv[1], "-v") == 0) { + verbose = 1; + argc--; + argv++; + } + + if (argc != 1) + format(); + + n = recursive_session_key_scan(act_keyctl_reap_func, NULL); + printf("%d keys reaped\n", n); + exit(0); +} + +struct purge_data { + const char *type; + const char *desc; + size_t desc_len; + size_t type_len; + char prefix_match; + char case_indep; +}; + +/* + * Attempt to unlink a key matching the type + */ +static int act_keyctl_purge_type_func(key_serial_t parent, key_serial_t key, + char *raw, int raw_len, void *data) +{ + const struct purge_data *purge = data; + char *p, *type; + + if (parent == 0 || !raw) + return 0; + + /* type is everything before the first semicolon */ + type = raw; + p = memchr(raw, ';', raw_len); + if (!p) + return 0; + *p = 0; + if (strcmp(type, purge->type) != 0) + return 0; + + return keyctl_unlink(key, parent) < 0 ? 0 : 1; +} + +/* + * Attempt to unlink a key matching the type and description literally + */ +static int act_keyctl_purge_literal_func(key_serial_t parent, key_serial_t key, + char *raw, int raw_len, void *data) +{ + const struct purge_data *purge = data; + size_t tlen; + char *p, *type, *desc; + + if (parent == 0 || !raw) + return 0; + + /* type is everything before the first semicolon */ + type = raw; + p = memchr(type, ';', raw_len); + if (!p) + return 0; + + tlen = p - type; + if (tlen != purge->type_len) + return 0; + if (memcmp(type, purge->type, tlen) != 0) + return 0; + + /* description is everything after the last semicolon */ + p++; + desc = memrchr(p, ';', raw + raw_len - p); + if (!desc) + return 0; + desc++; + + if (purge->prefix_match) { + if (raw_len - (desc - raw) < purge->desc_len) + return 0; + } else { + if (raw_len - (desc - raw) != purge->desc_len) + return 0; + } + + if (purge->case_indep) { + if (strncasecmp(purge->desc, desc, purge->desc_len) != 0) + return 0; + } else { + if (memcmp(purge->desc, desc, purge->desc_len) != 0) + return 0; + } + + printf("%*.*s '%s'\n", (int)tlen, (int)tlen, type, desc); + + return keyctl_unlink(key, parent) < 0 ? 0 : 1; +} + +/* + * Attempt to unlink a key matching the type and description literally + */ +static int act_keyctl_purge_search_func(key_serial_t parent, key_serial_t keyring, + char *raw, int raw_len, void *data) +{ + const struct purge_data *purge = data; + key_serial_t key; + int kcount = 0; + + if (!raw || memcmp(raw, "keyring;", 8) != 0) + return 0; + + for (;;) { + key = keyctl_search(keyring, purge->type, purge->desc, 0); + if (keyctl_unlink(key, keyring) < 0) + return kcount; + kcount++; + } + return kcount; +} + +/* + * Purge matching keys from a keyring + */ +static void act_keyctl_purge(int argc, char *argv[]) +{ + recursive_key_scanner_t func; + struct purge_data purge = { + .prefix_match = 0, + .case_indep = 0, + }; + int n = 0, search_mode = 0; + + argc--; + argv++; + while (argc > 0 && argv[0][0] == '-') { + if (argv[0][1] == 's') + search_mode = 1; + else if (argv[0][1] == 'p') + purge.prefix_match = 1; + else if (argv[0][1] == 'i') + purge.case_indep = 1; + else + format(); + argc--; + argv++; + } + + if (argc < 1) + format(); + + purge.type = argv[0]; + purge.desc = argv[1]; + purge.type_len = strlen(purge.type); + purge.desc_len = purge.desc ? strlen(purge.desc) : 0; + + if (search_mode == 1) { + if (argc != 2 || purge.prefix_match || purge.case_indep) + format(); + /* purge all keys of a specific type and description, according + * to the kernel's comparator */ + func = act_keyctl_purge_search_func; + } else if (argc == 1) { + if (purge.prefix_match || purge.case_indep) + format(); + /* purge all keys of a specific type */ + func = act_keyctl_purge_type_func; + } else if (argc == 2) { + /* purge all keys of a specific type with literally matching + * description */ + func = act_keyctl_purge_literal_func; + } else { + format(); + } + + n = recursive_session_key_scan(func, &purge); + printf("purged %d keys\n", n); + exit(0); +} + +/*****************************************************************************/ +/* + * Invalidate a key + */ +static void act_keyctl_invalidate(int argc, char *argv[]) +{ + key_serial_t key; + + if (argc != 2) + format(); + + key = get_key_id(argv[1]); + + if (keyctl_invalidate(key) < 0) + error("keyctl_invalidate"); + + exit(0); +} + +/*****************************************************************************/ +/* + * Get the per-UID persistent keyring + */ +static void act_keyctl_get_persistent(int argc, char *argv[]) +{ + key_serial_t dest, ret; + uid_t uid = -1; + char *q; + + if (argc != 2 && argc != 3) + format(); + + dest = get_key_id(argv[1]); + + if (argc > 2) { + uid = strtoul(argv[2], &q, 0); + if (*q) { + fprintf(stderr, "Unparsable uid: '%s'\n", argv[2]); + exit(2); + } + } + + ret = keyctl_get_persistent(uid, dest); + if (ret < 0) + error("keyctl_get_persistent"); + + /* print the resulting key ID */ + printf("%d\n", ret); + exit(0); +} + +/*****************************************************************************/ +/* + * Perform Diffie-Hellman computation + */ +static void act_keyctl_dh_compute(int argc, char *argv[]) +{ + key_serial_t priv, prime, base; + void *buffer; + char *p; + int ret, sep, col; + + if (argc != 4) + format(); + + priv = get_key_id(argv[1]); + prime = get_key_id(argv[2]); + base = get_key_id(argv[3]); + + ret = keyctl_dh_compute_alloc(priv, prime, base, &buffer); + if (ret < 0) + error("keyctl_dh_compute_alloc"); + + /* hexdump the contents */ + printf("%u bytes of data in result:\n", ret); + + sep = 0; + col = 0; + p = buffer; + + do { + if (sep) { + putchar(sep); + sep = 0; + } + + printf("%02hhx", *p); + *p = 0x00; /* zeroize buffer */ + p++; + + col++; + if (col % 32 == 0) + sep = '\n'; + else if (col % 4 == 0) + sep = ' '; + + } while (--ret > 0); + + printf("\n"); + + free(buffer); + + exit(0); +} + +static void act_keyctl_dh_compute_kdf(int argc, char *argv[]) +{ + key_serial_t private, prime, base; + char *buffer; + char *p; + int ret, sep, col; + unsigned long buflen = 0; + + if (argc != 6) + format(); + + private = get_key_id(argv[1]); + prime = get_key_id(argv[2]); + base = get_key_id(argv[3]); + + buflen = strtoul(argv[4], NULL, 10); + if (buflen == ULONG_MAX) + error("dh_compute: cannot convert generated length value"); + + buffer = malloc(buflen); + if (!buffer) + error("dh_compute: cannot allocate memory"); + + ret = keyctl_dh_compute_kdf(private, prime, base, argv[5], NULL, 0, + buffer, buflen); + if (ret < 0) + error("keyctl_dh_compute_kdf"); + + /* hexdump the contents */ + printf("%u bytes of data in result:\n", ret); + + sep = 0; + col = 0; + p = buffer; + + do { + if (sep) { + putchar(sep); + sep = 0; + } + + printf("%02hhx", *p); + *p = 0x00; /* zeroize buffer */ + p++; + + col++; + if (col % 32 == 0) + sep = '\n'; + else if (col % 4 == 0) + sep = ' '; + + } while (--ret > 0); + + printf("\n"); + + free(buffer); + + exit(0); +} + +static void act_keyctl_dh_compute_kdf_oi(int argc, char *argv[]) +{ + key_serial_t private, prime, base; + char *buffer; + char *p; + int ret, sep, col; + unsigned long buflen = 0; + size_t oilen; + void *oi; + + if (argc != 6) + format(); + + private = get_key_id(argv[1]); + prime = get_key_id(argv[2]); + base = get_key_id(argv[3]); + + buflen = strtoul(argv[4], NULL, 10); + if (buflen == ULONG_MAX) + error("dh_compute: cannot convert generated length value"); + + buffer = malloc(buflen); + if (!buffer) + error("dh_compute: cannot allocate memory"); + + oi = grab_stdin(&oilen); + + ret = keyctl_dh_compute_kdf(private, prime, base, argv[5], oi, oilen, + buffer, buflen); + if (ret < 0) + error("keyctl_dh_compute_kdf"); + + /* hexdump the contents */ + printf("%u bytes of data in result:\n", ret); + + sep = 0; + col = 0; + p = buffer; + + do { + if (sep) { + putchar(sep); + sep = 0; + } + + printf("%02hhx", *p); + *p = 0x00; /* zeroize buffer */ + p++; + + col++; + if (col % 32 == 0) + sep = '\n'; + else if (col % 4 == 0) + sep = ' '; + + } while (--ret > 0); + + printf("\n"); + + free(buffer); + + exit(0); +} + +/*****************************************************************************/ +/* + * Restrict the keys that may be added to a keyring + */ +static void act_keyctl_restrict_keyring(int argc, char *argv[]) +{ + key_serial_t keyring; + char *type = NULL; + char *restriction = NULL; + long ret; + + if (argc < 2 || argc > 4) + format(); + + keyring = get_key_id(argv[1]); + + if (argc > 2) + type = argv[2]; + + if (argc == 4) + restriction = argv[3]; + + ret = keyctl_restrict_keyring(keyring, type, restriction); + if (ret < 0) + error("keyctl_restrict_keyring"); + + exit(0); +} + +/* + * Parse public key operation info arguments. + */ +static void pkey_parse_info(char **argv, char info[4096]) +{ + int i_len = 0; + + /* A number of key=val pairs can be provided after the main arguments + * to inform the kernel of things like encoding type and hash function. + */ + for (; *argv; argv++) { + int n = strlen(argv[0]); + + if (!memchr(argv[0], '=', n)) { + fprintf(stderr, "Option not in key=val form\n"); + exit(2); + } + if (n + 1 > 4096 - 1 - i_len) { + fprintf(stderr, "Too many info options\n"); + exit(2); + } + + if (i_len > 0) + info[i_len++] = ' '; + memcpy(info + i_len, argv[0], n); + i_len += n; + } + + info[i_len] = 0; +} + +/* + * Query a public key. + */ +static void act_keyctl_pkey_query(int argc, char *argv[]) +{ + struct keyctl_pkey_query result; + key_serial_t key; + char info[4096]; + + if (argc < 3) + format(); + pkey_parse_info(argv + 3, info); + + key = get_key_id(argv[1]); + if (strcmp(argv[2], "0") != 0) { + fprintf(stderr, "Password passing is not yet supported\n"); + exit(2); + } + + if (keyctl_pkey_query(key, info, &result) < 0) + error("keyctl_pkey_query"); + + printf("key_size=%u\n", result.key_size); + printf("max_data_size=%u\n", result.max_data_size); + printf("max_sig_size=%u\n", result.max_sig_size); + printf("max_enc_size=%u\n", result.max_enc_size); + printf("max_dec_size=%u\n", result.max_dec_size); + printf("encrypt=%c\n", result.supported_ops & KEYCTL_SUPPORTS_ENCRYPT ? 'y' : 'n'); + printf("decrypt=%c\n", result.supported_ops & KEYCTL_SUPPORTS_DECRYPT ? 'y' : 'n'); + printf("sign=%c\n", result.supported_ops & KEYCTL_SUPPORTS_SIGN ? 'y' : 'n'); + printf("verify=%c\n", result.supported_ops & KEYCTL_SUPPORTS_VERIFY ? 'y' : 'n'); + exit(0); +} + +/* + * Encrypt a blob. + */ +static void act_keyctl_pkey_encrypt(int argc, char *argv[]) +{ + struct keyctl_pkey_query result; + key_serial_t key; + size_t in_len; + long out_len; + void *in, *out; + char info[4096]; + + if (argc < 4) + format(); + pkey_parse_info(argv + 4, info); + + key = get_key_id(argv[1]); + if (strcmp(argv[2], "0") != 0) { + fprintf(stderr, "Password passing is not yet supported\n"); + exit(2); + } + in = read_file(argv[3], &in_len); + + if (keyctl_pkey_query(key, info, &result) < 0) + error("keyctl_pkey_query"); + + out = malloc(result.max_dec_size); + if (!out) + error("malloc"); + + out_len = keyctl_pkey_encrypt(key, info, + in, in_len, out, result.max_dec_size); + if (out_len < 0) + error("keyctl_pkey_encrypt"); + + if (fwrite(out, out_len, 1, stdout) != 1) + error("stdout"); + exit(0); +} + +/* + * Decrypt a blob. + */ +static void act_keyctl_pkey_decrypt(int argc, char *argv[]) +{ + struct keyctl_pkey_query result; + key_serial_t key; + size_t in_len; + long out_len; + void *in, *out; + char info[4096]; + + if (argc < 4) + format(); + pkey_parse_info(argv + 4, info); + + key = get_key_id(argv[1]); + if (strcmp(argv[2], "0") != 0) { + fprintf(stderr, "Password passing is not yet supported\n"); + exit(2); + } + in = read_file(argv[3], &in_len); + + if (keyctl_pkey_query(key, info, &result) < 0) + error("keyctl_pkey_query"); + + out = malloc(result.max_enc_size); + if (!out) + error("malloc"); + + out_len = keyctl_pkey_decrypt(key, info, + in, in_len, out, result.max_enc_size); + if (out_len < 0) + error("keyctl_pkey_decrypt"); + + if (fwrite(out, out_len, 1, stdout) != 1) + error("stdout"); + exit(0); +} + +/* + * Create a signature + */ +static void act_keyctl_pkey_sign(int argc, char *argv[]) +{ + struct keyctl_pkey_query result; + key_serial_t key; + size_t in_len; + long out_len; + void *in, *out; + char info[4096]; + + if (argc < 4) + format(); + pkey_parse_info(argv + 4, info); + + key = get_key_id(argv[1]); + if (strcmp(argv[2], "0") != 0) { + fprintf(stderr, "Password passing is not yet supported\n"); + exit(2); + } + in = read_file(argv[3], &in_len); + + if (keyctl_pkey_query(key, info, &result) < 0) + error("keyctl_pkey_query"); + + out = malloc(result.max_sig_size); + if (!out) + error("malloc"); + + out_len = keyctl_pkey_sign(key, info, + in, in_len, out, result.max_sig_size); + if (out_len < 0) + error("keyctl_pkey_sign"); + + if (fwrite(out, out_len, 1, stdout) != 1) + error("stdout"); + exit(0); +} + +/* + * Verify a signature. + */ +static void act_keyctl_pkey_verify(int argc, char *argv[]) +{ + key_serial_t key; + size_t data_len, sig_len; + void *data, *sig; + char info[4096]; + + if (argc < 5) + format(); + pkey_parse_info(argv + 5, info); + + key = get_key_id(argv[1]); + if (strcmp(argv[2], "0") != 0) { + fprintf(stderr, "Password passing is not yet supported\n"); + exit(2); + } + data = read_file(argv[3], &data_len); + sig = read_file(argv[4], &sig_len); + + if (keyctl_pkey_verify(key, info, + data, data_len, sig, sig_len) < 0) + error("keyctl_pkey_verify"); + exit(0); +} + +/* + * Move a key between keyrings. + */ +static void act_keyctl_move(int argc, char *argv[]) +{ + key_serial_t key, from_keyring, to_keyring; + unsigned int flags = KEYCTL_MOVE_EXCL; + + if (argc > 4) { + if (strcmp("-f", argv[1]) == 0) { + flags &= ~KEYCTL_MOVE_EXCL; + argc--; + argv++; + } + } + + if (argc != 4) + format(); + + key = get_key_id(argv[1]); + from_keyring = get_key_id(argv[2]); + to_keyring = get_key_id(argv[3]); + + if (keyctl_move(key, from_keyring, to_keyring, flags) < 0) + error("keyctl_move"); + + exit(0); +} + +struct capability_def { + const char *name; /* Textual name of capability */ + unsigned int index; /* Index in capabilities array */ + unsigned char mask; /* Mask on capabilities array element */ +}; + +static const struct capability_def capabilities[] = { + { "capabilities", 0, KEYCTL_CAPS0_CAPABILITIES }, + { "persistent_keyrings", 0, KEYCTL_CAPS0_PERSISTENT_KEYRINGS }, + { "dh_compute", 0, KEYCTL_CAPS0_DIFFIE_HELLMAN }, + { "public_key", 0, KEYCTL_CAPS0_PUBLIC_KEY }, + { "big_key_type", 0, KEYCTL_CAPS0_BIG_KEY }, + { "key_invalidate", 0, KEYCTL_CAPS0_INVALIDATE }, + { "restrict_keyring", 0, KEYCTL_CAPS0_RESTRICT_KEYRING }, + { "move_key", 0, KEYCTL_CAPS0_MOVE }, + {} +}; + +/* + * Detect/list capabilities. + */ +static void act_keyctl_supports(int argc, char *argv[]) +{ + const struct capability_def *p; + unsigned char caps[256]; + + if (argc < 1 || argc > 2) + format(); + + if (keyctl_capabilities(caps, sizeof(caps)) < 0) + error("keyctl_capabilities"); + + if (argc == 1) { + for (p = capabilities; p->name; p++) + printf("have_%s=%c\n", + p->name, + (caps[p->index] & p->mask) ? '1' : '0'); + exit(0); + } else { + for (p = capabilities; p->name; p++) + if (strcmp(argv[1], p->name) == 0) + exit((caps[p->index] & p->mask) ? 0 : 1); + exit(3); + } +} + +/*****************************************************************************/ +/* + * parse a key identifier + */ +static key_serial_t get_key_id(char *arg) +{ + key_serial_t id; + char *end; + + /* handle a special keyring name */ + if (arg[0] == '@') { + if (strcmp(arg, "@t" ) == 0) return KEY_SPEC_THREAD_KEYRING; + if (strcmp(arg, "@p" ) == 0) return KEY_SPEC_PROCESS_KEYRING; + if (strcmp(arg, "@s" ) == 0) return KEY_SPEC_SESSION_KEYRING; + if (strcmp(arg, "@u" ) == 0) return KEY_SPEC_USER_KEYRING; + if (strcmp(arg, "@us") == 0) return KEY_SPEC_USER_SESSION_KEYRING; + if (strcmp(arg, "@g" ) == 0) return KEY_SPEC_GROUP_KEYRING; + if (strcmp(arg, "@a" ) == 0) return KEY_SPEC_REQKEY_AUTH_KEY; + + fprintf(stderr, "Unknown special key: '%s'\n", arg); + exit(2); + } + + /* handle a lookup-by-name request "%:", eg: "%keyring:_ses" */ + if (arg[0] == '%') { + char *type; + + arg++; + if (!*arg) + goto incorrect_key_by_name_spec; + + if (*arg == ':') { + type = "keyring"; + arg++; + } else { + type = arg; + arg = strchr(arg, ':'); + if (!arg) + goto incorrect_key_by_name_spec; + *(arg++) = '\0'; + } + + if (!*arg) + goto incorrect_key_by_name_spec; + + id = find_key_by_type_and_desc(type, arg, 0); + if (id == -1) { + fprintf(stderr, "Can't find '%s:%s'\n", type, arg); + exit(1); + } + return id; + } + + /* handle a numeric key ID */ + id = strtoul(arg, &end, 0); + if (*end) { + fprintf(stderr, "Unparsable key: '%s'\n", arg); + exit(2); + } + + return id; + +incorrect_key_by_name_spec: + fprintf(stderr, "Incorrect key-by-name spec\n"); + exit(2); + +} /* end get_key_id() */ + +/* + * Read the contents of a file into a buffer and return it. + */ +static void *read_file(const char *name, size_t *_size) +{ + struct stat st; + ssize_t r; + void *p; + int fd; + + fd = open(name, O_RDONLY); + if (fd < 0) + error(name); + if (fstat(fd, &st) < 0) + error(name); + + p = malloc(st.st_size); + if (!p) + error("malloc"); + r = read(fd, p, st.st_size); + if (r == -1) + error(name); + if (r != st.st_size) { + fprintf(stderr, "%s: Short read\n", name); + exit(1); + } + if (close(fd) < 0) + error(name); + + *_size = st.st_size; + return p; +} + +/*****************************************************************************/ +/* + * recursively display a key/keyring tree + */ +static int dump_key_tree_aux(key_serial_t key, int depth, int more, int hex_key_IDs) +{ + static char dumpindent[64]; + key_serial_t *pk; + key_perm_t perm; + size_t ringlen; + void *payload; + char *desc, type[255], pretty_mask[9]; + int uid, gid, ret, n, dpos, rdepth, kcount = 0; + + if (depth > 8 * 4) + return 0; + + /* read the description */ + ret = keyctl_describe_alloc(key, &desc); + if (ret < 0) { + printf("%d: key inaccessible (%m)\n", key); + return 0; + } + + /* parse */ + type[0] = 0; + uid = 0; + gid = 0; + perm = 0; + + n = sscanf(desc, "%[^;];%d;%d;%x;%n", + type, &uid, &gid, &perm, &dpos); + + if (n != 4) { + fprintf(stderr, "Unparseable description obtained for key %d\n", key); + exit(3); + } + + /* and print */ + calc_perms(pretty_mask, perm, uid, gid); + + if (hex_key_IDs) + printf("0x%08x %s %5d %5d %s%s%s: %s\n", + key, + pretty_mask, + uid, gid, + dumpindent, + depth > 0 ? "\\_ " : "", + type, desc + dpos); + else + printf("%10d %s %5d %5d %s%s%s: %s\n", + key, + pretty_mask, + uid, gid, + dumpindent, + depth > 0 ? "\\_ " : "", + type, desc + dpos); + + free(desc); + + /* if it's a keyring then we're going to want to recursively + * display it if we can */ + if (strcmp(type, "keyring") == 0) { + /* read its contents */ + ret = keyctl_read_alloc(key, &payload); + if (ret < 0) + error("keyctl_read_alloc"); + + ringlen = ret; + kcount = ringlen / sizeof(key_serial_t); + + /* walk the keyring */ + pk = payload; + while (ringlen >= sizeof(key_serial_t)) { + key = *pk++; + + /* recurse into next keyrings */ + if (strcmp(type, "keyring") == 0) { + if (depth == 0) { + rdepth = depth; + dumpindent[rdepth++] = ' '; + dumpindent[rdepth] = 0; + } + else { + rdepth = depth; + dumpindent[rdepth++] = ' '; + dumpindent[rdepth++] = ' '; + dumpindent[rdepth++] = ' '; + dumpindent[rdepth++] = ' '; + dumpindent[rdepth] = 0; + } + + if (more) + dumpindent[depth + 0] = '|'; + + kcount += dump_key_tree_aux(key, + rdepth, + ringlen - 4 >= sizeof(key_serial_t), + hex_key_IDs); + } + + ringlen -= sizeof(key_serial_t); + } + + free(payload); + } + + return kcount; + +} /* end dump_key_tree_aux() */ + +/*****************************************************************************/ +/* + * recursively list a keyring's contents + */ +static int dump_key_tree(key_serial_t keyring, const char *name, int hex_key_IDs) +{ + printf("%s\n", name); + + keyring = keyctl_get_keyring_ID(keyring, 0); + if (keyring == -1) + error("Unable to dump key"); + + return dump_key_tree_aux(keyring, 0, 0, hex_key_IDs); + +} /* end dump_key_tree() */ diff --git a/keyutils.c b/keyutils.c new file mode 100644 index 0000000000..9c37256241 --- /dev/null +++ b/keyutils.c @@ -0,0 +1,880 @@ +/* keyutils.c: key utility library + * + * Copyright (C) 2005,2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "keyutils.h" + +const char keyutils_version_string[] = PKGVERSION; +const char keyutils_build_string[] = PKGBUILD; + +#ifdef NO_GLIBC_KEYERR +static int error_inited; +static void (*libc_perror)(const char *msg); +static char *(*libc_strerror_r)(int errnum, char *buf, size_t n); +//static int (*libc_xpg_strerror_r)(int errnum, char *buf, size_t n); +#define RTLD_NEXT ((void *) -1L) +#endif + +#define __weak __attribute__((weak)) + +key_serial_t __weak add_key(const char *type, + const char *description, + const void *payload, + size_t plen, + key_serial_t ringid) +{ + return syscall(__NR_add_key, + type, description, payload, plen, ringid); +} + +key_serial_t __weak request_key(const char *type, + const char *description, + const char * callout_info, + key_serial_t destringid) +{ + return syscall(__NR_request_key, + type, description, callout_info, destringid); +} + +static inline long __keyctl(int cmd, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5) +{ + return syscall(__NR_keyctl, + cmd, arg2, arg3, arg4, arg5); +} + +long __weak keyctl(int cmd, ...) +{ + va_list va; + unsigned long arg2, arg3, arg4, arg5; + + va_start(va, cmd); + arg2 = va_arg(va, unsigned long); + arg3 = va_arg(va, unsigned long); + arg4 = va_arg(va, unsigned long); + arg5 = va_arg(va, unsigned long); + va_end(va); + + return __keyctl(cmd, arg2, arg3, arg4, arg5); +} + +key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create) +{ + return keyctl(KEYCTL_GET_KEYRING_ID, id, create); +} + +key_serial_t keyctl_join_session_keyring(const char *name) +{ + return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name); +} + +long keyctl_update(key_serial_t id, const void *payload, size_t plen) +{ + return keyctl(KEYCTL_UPDATE, id, payload, plen); +} + +long keyctl_revoke(key_serial_t id) +{ + return keyctl(KEYCTL_REVOKE, id); +} + +long keyctl_chown(key_serial_t id, uid_t uid, gid_t gid) +{ + return keyctl(KEYCTL_CHOWN, id, uid, gid); +} + +long keyctl_setperm(key_serial_t id, key_perm_t perm) +{ + return keyctl(KEYCTL_SETPERM, id, perm); +} + +long keyctl_describe(key_serial_t id, char *buffer, size_t buflen) +{ + return keyctl(KEYCTL_DESCRIBE, id, buffer, buflen); +} + +long keyctl_clear(key_serial_t ringid) +{ + return keyctl(KEYCTL_CLEAR, ringid); +} + +long keyctl_link(key_serial_t id, key_serial_t ringid) +{ + return keyctl(KEYCTL_LINK, id, ringid); +} + +long keyctl_unlink(key_serial_t id, key_serial_t ringid) +{ + return keyctl(KEYCTL_UNLINK, id, ringid); +} + +long keyctl_search(key_serial_t ringid, + const char *type, + const char *description, + key_serial_t destringid) +{ + return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid); +} + +long keyctl_read(key_serial_t id, char *buffer, size_t buflen) +{ + return keyctl(KEYCTL_READ, id, buffer, buflen); +} + +long keyctl_instantiate(key_serial_t id, + const void *payload, + size_t plen, + key_serial_t ringid) +{ + return keyctl(KEYCTL_INSTANTIATE, id, payload, plen, ringid); +} + +long keyctl_negate(key_serial_t id, unsigned timeout, key_serial_t ringid) +{ + return keyctl(KEYCTL_NEGATE, id, timeout, ringid); +} + +long keyctl_set_reqkey_keyring(int reqkey_defl) +{ + return keyctl(KEYCTL_SET_REQKEY_KEYRING, reqkey_defl); +} + +long keyctl_set_timeout(key_serial_t id, unsigned timeout) +{ + return keyctl(KEYCTL_SET_TIMEOUT, id, timeout); +} + +long keyctl_assume_authority(key_serial_t id) +{ + return keyctl(KEYCTL_ASSUME_AUTHORITY, id); +} + +long keyctl_get_security(key_serial_t id, char *buffer, size_t buflen) +{ + return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen); +} + +long keyctl_session_to_parent(void) +{ + return keyctl(KEYCTL_SESSION_TO_PARENT); +} + +long keyctl_reject(key_serial_t id, unsigned timeout, unsigned error, + key_serial_t ringid) +{ + long ret = keyctl(KEYCTL_REJECT, id, timeout, error, ringid); + + /* fall back to keyctl_negate() if this op is not supported by this + * kernel version */ + if (ret == -1 && errno == EOPNOTSUPP) + return keyctl_negate(id, timeout, ringid); + return ret; +} + +long keyctl_instantiate_iov(key_serial_t id, + const struct iovec *payload_iov, + unsigned ioc, + key_serial_t ringid) +{ + long ret = keyctl(KEYCTL_INSTANTIATE_IOV, id, payload_iov, ioc, ringid); + + /* fall back to keyctl_instantiate() if this op is not supported by + * this kernel version */ + if (ret == -1 && errno == EOPNOTSUPP) { + unsigned loop; + size_t bsize = 0, seg; + void *buf, *p; + + if (!payload_iov || !ioc) + return keyctl_instantiate(id, NULL, 0, ringid); + for (loop = 0; loop < ioc; loop++) + bsize += payload_iov[loop].iov_len; + if (bsize == 0) + return keyctl_instantiate(id, NULL, 0, ringid); + p = buf = malloc(bsize); + if (!buf) + return -1; + for (loop = 0; loop < ioc; loop++) { + seg = payload_iov[loop].iov_len; + p = memcpy(p, payload_iov[loop].iov_base, seg) + seg; + } + ret = keyctl_instantiate(id, buf, bsize, ringid); + free(buf); + } + return ret; +} + +long keyctl_invalidate(key_serial_t id) +{ + return keyctl(KEYCTL_INVALIDATE, id); +} + +long keyctl_get_persistent(uid_t uid, key_serial_t id) +{ + return keyctl(KEYCTL_GET_PERSISTENT, uid, id); +} + +long keyctl_dh_compute(key_serial_t priv, key_serial_t prime, + key_serial_t base, char *buffer, size_t buflen) +{ + struct keyctl_dh_params params = { .priv = priv, + .prime = prime, + .base = base }; + + return keyctl(KEYCTL_DH_COMPUTE, ¶ms, buffer, buflen, 0); +} + +long keyctl_dh_compute_kdf(key_serial_t private, key_serial_t prime, + key_serial_t base, char *hashname, char *otherinfo, + size_t otherinfolen, char *buffer, size_t buflen) +{ + struct keyctl_dh_params params = { .priv = private, + .prime = prime, + .base = base }; + struct keyctl_kdf_params kdfparams = { .hashname = hashname, + .otherinfo = otherinfo, + .otherinfolen = otherinfolen }; + + return keyctl(KEYCTL_DH_COMPUTE, ¶ms, buffer, buflen, &kdfparams); +} + +long keyctl_restrict_keyring(key_serial_t keyring, const char *type, + const char *restriction) +{ + return keyctl(KEYCTL_RESTRICT_KEYRING, keyring, type, restriction); +} + +long keyctl_pkey_query(key_serial_t key_id, + const char *info, + struct keyctl_pkey_query *result) +{ + return keyctl(KEYCTL_PKEY_QUERY, key_id, NULL, info, result); +} + +long keyctl_pkey_encrypt(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + void *enc, size_t enc_len) +{ + struct keyctl_pkey_params params = { + .key_id = key_id, + .in_len = data_len, + .out_len = enc_len, + }; + + return keyctl(KEYCTL_PKEY_ENCRYPT, ¶ms, info, data, enc); +} + +long keyctl_pkey_decrypt(key_serial_t key_id, + const char *info, + const void *enc, size_t enc_len, + void *data, size_t data_len) +{ + struct keyctl_pkey_params params = { + .key_id = key_id, + .in_len = enc_len, + .out_len = data_len, + }; + + return keyctl(KEYCTL_PKEY_DECRYPT, ¶ms, info, enc, data); +} + +long keyctl_pkey_sign(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + void *sig, size_t sig_len) +{ + struct keyctl_pkey_params params = { + .key_id = key_id, + .in_len = data_len, + .out_len = sig_len, + }; + + return keyctl(KEYCTL_PKEY_SIGN, ¶ms, info, data, sig); +} + +long keyctl_pkey_verify(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + const void *sig, size_t sig_len) +{ + struct keyctl_pkey_params params = { + .key_id = key_id, + .in_len = data_len, + .in2_len = sig_len, + }; + + return keyctl(KEYCTL_PKEY_VERIFY, ¶ms, info, data, sig); +} + +long keyctl_move(key_serial_t id, + key_serial_t from_ringid, + key_serial_t to_ringid, + unsigned int flags) +{ + return keyctl(KEYCTL_MOVE, id, from_ringid, to_ringid, flags); +} + +long keyctl_capabilities(unsigned char *buffer, size_t buflen) +{ + long n; + + n = keyctl(KEYCTL_CAPABILITIES, buffer, buflen); + if (n != -1 || errno != EOPNOTSUPP) + return n; + + /* Emulate the operation */ + if (buflen > 0) { + memset(buffer, 0, buflen); + + errno = 0; + keyctl_get_persistent(-1, 0); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_PERSISTENT_KEYRINGS; + + errno = 0; + keyctl_dh_compute(0, 0, 0, NULL, 0); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_DIFFIE_HELLMAN; + + errno = 0; + keyctl_pkey_query(0, NULL, NULL); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_PUBLIC_KEY; + + /* Can't emulate KEYCTL_CAPS0_BIG_KEY without a valid + * destination keyring. + */ + + errno = 0; + keyctl_invalidate(0); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_INVALIDATE; + + errno = 0; + keyctl_restrict_keyring(0, NULL, NULL); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_RESTRICT_KEYRING; + + errno = 0; + keyctl_move(0, 0, 0, 0); + if (errno != EOPNOTSUPP) + buffer[0] |= KEYCTL_CAPS0_MOVE; + } + + return sizeof(unsigned char); +} + +/*****************************************************************************/ +/* + * fetch key description into an allocated buffer + * - resulting string is NUL terminated + * - returns count not including NUL + */ +int keyctl_describe_alloc(key_serial_t id, char **_buffer) +{ + char *buf; + long buflen, ret; + + ret = keyctl_describe(id, NULL, 0); + if (ret < 0) + return -1; + + for (;;) { + buflen = ret; + buf = malloc(buflen); + if (!buf) + return -1; + + ret = keyctl_describe(id, buf, buflen); + if (ret < 0) { + free(buf); + return -1; + } + + if (buflen >= ret) + break; + free(buf); + } + + *_buffer = buf; + return ret - 1; +} + +/*****************************************************************************/ +/* + * fetch key contents into an allocated buffer + * - resulting buffer has an extra NUL added to the end + * - returns count (not including extraneous NUL) + */ +int keyctl_read_alloc(key_serial_t id, void **_buffer) +{ + char *buf; + long buflen, ret; + + ret = keyctl_read(id, NULL, 0); + if (ret < 0) + return -1; + + for (;;) { + buflen = ret; + buf = malloc(buflen + 1); + if (!buf) + return -1; + + ret = keyctl_read(id, buf, buflen); + if (ret < 0) { + free(buf); + return -1; + } + + if (buflen >= ret) + break; + free(buf); + } + + buf[ret] = 0; + *_buffer = buf; + return ret; +} + +/*****************************************************************************/ +/* + * fetch key security label into an allocated buffer + * - resulting string is NUL terminated + * - returns count not including NUL + */ +int keyctl_get_security_alloc(key_serial_t id, char **_buffer) +{ + char *buf; + long buflen, ret; + + ret = keyctl_get_security(id, NULL, 0); + if (ret < 0) + return -1; + + for (;;) { + buflen = ret; + buf = malloc(buflen); + if (!buf) + return -1; + + ret = keyctl_get_security(id, buf, buflen); + if (ret < 0) { + free(buf); + return -1; + } + + if (buflen >= ret) + break; + free(buf); + } + + *_buffer = buf; + return ret - 1; +} + +/*****************************************************************************/ +/* + * fetch DH computation results into an allocated buffer + * - resulting buffer has an extra NUL added to the end + * - returns count (not including extraneous NUL) + */ +int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime, + key_serial_t base, void **_buffer) +{ + char *buf; + long buflen, ret; + + ret = keyctl_dh_compute(priv, prime, base, NULL, 0); + if (ret < 0) + return -1; + + buflen = ret; + buf = malloc(buflen + 1); + if (!buf) + return -1; + + ret = keyctl_dh_compute(priv, prime, base, buf, buflen); + if (ret < 0) { + free(buf); + return -1; + } + + buf[ret] = 0; + *_buffer = buf; + return ret; +} + +/* + * Depth-first recursively apply a function over a keyring tree + */ +static int recursive_key_scan_aux(key_serial_t parent, key_serial_t key, + int depth, recursive_key_scanner_t func, + void *data) +{ + key_serial_t *pk; + key_perm_t perm; + size_t ringlen; + void *ring; + char *desc, type[255]; + int desc_len, uid, gid, ret, n, kcount = 0; + + if (depth > 800) + return 0; + + /* read the key description */ + desc = NULL; + desc_len = keyctl_describe_alloc(key, &desc); + if (desc_len < 0) + goto do_this_key; + + /* parse */ + type[0] = 0; + + n = sscanf(desc, "%[^;];%d;%d;%x;", type, &uid, &gid, &perm); + if (n != 4) { + free(desc); + desc = NULL; + errno = -EINVAL; + desc_len = -1; + goto do_this_key; + } + + /* if it's a keyring then we're going to want to recursively search it + * if we can */ + if (strcmp(type, "keyring") == 0) { + /* read the keyring's contents */ + ret = keyctl_read_alloc(key, &ring); + if (ret < 0) + goto do_this_key; + + ringlen = ret; + + /* walk the keyring */ + pk = ring; + for (ringlen = ret; + ringlen >= sizeof(key_serial_t); + ringlen -= sizeof(key_serial_t) + ) + kcount += recursive_key_scan_aux(key, *pk++, depth + 1, + func, data); + + free(ring); + } + +do_this_key: + kcount += func(parent, key, desc, desc_len, data); + free(desc); + return kcount; +} + +/* + * Depth-first apply a function over a keyring tree + */ +int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data) +{ + return recursive_key_scan_aux(0, key, 0, func, data); +} + +/* + * Depth-first apply a function over session keyring tree + */ +int recursive_session_key_scan(recursive_key_scanner_t func, void *data) +{ + key_serial_t session = + keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); + if (session > 0) + return recursive_key_scan(session, func, data); + return 0; +} + +/* + * Find a key by type and description + */ +key_serial_t find_key_by_type_and_desc(const char *type, const char *desc, + key_serial_t destringid) +{ + key_serial_t id, error; + FILE *f; + char buf[1024], typebuf[40], rdesc[1024], *kdesc, *cp; + int n, ndesc, dlen; + + error = ENOKEY; + + id = request_key(type, desc, NULL, destringid); + if (id >= 0 || errno == ENOMEM) + return id; + if (errno != ENOKEY) + error = errno; + + dlen = strlen(desc); + + f = fopen("/proc/keys", "r"); + if (!f) { + fprintf(stderr, "libkeyutils: Can't open /proc/keys: %m\n"); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) { + cp = strchr(buf, '\n'); + if (*cp) + *cp = '\0'; + + ndesc = 0; + n = sscanf(buf, "%x %*s %*u %*s %*x %*d %*d %s %n", + &id, typebuf, &ndesc); + if (n == 2 && ndesc > 0 && ndesc <= cp - buf) { + if (strcmp(typebuf, type) != 0) + continue; + kdesc = buf + ndesc; + if (memcmp(kdesc, desc, dlen) != 0) + continue; + if (kdesc[dlen] != ':' && + kdesc[dlen] != '\0' && + kdesc[dlen] != ' ') + continue; + kdesc[dlen] = '\0'; + + /* The key type appends extra stuff to the end of the + * description after a colon in /proc/keys. Colons, + * however, are allowed in descriptions, so we need to + * make a further check. */ + n = keyctl_describe(id, rdesc, sizeof(rdesc) - 1); + if (n == -1) { + if (errno != ENOKEY) + error = errno; + if (errno == ENOMEM) + break; + } + if (n >= sizeof(rdesc) - 1) + continue; + rdesc[n] = '\0'; + + cp = strrchr(rdesc, ';'); + if (!cp) + continue; + cp++; + if (strcmp(cp, desc) != 0) + continue; + + fclose(f); + + if (destringid && + keyctl_link(id, destringid) == -1) + return -1; + + return id; + } + } + + fclose(f); + errno = error; + return -1; +} + +#ifdef NO_GLIBC_KEYERR +/*****************************************************************************/ +/* + * initialise error handling + */ +static void error_init(void) +{ + char *err; + + error_inited = 1; + + dlerror(); + + libc_perror = dlsym(RTLD_NEXT,"perror"); + if (!libc_perror) { + fprintf(stderr, "Failed to look up next perror\n"); + err = dlerror(); + if (err) + fprintf(stderr, "%s\n", err); + abort(); + } + + //fprintf(stderr, "next perror at %p\n", libc_perror); + + libc_strerror_r = dlsym(RTLD_NEXT,"strerror_r"); + if (!libc_strerror_r) { + fprintf(stderr, "Failed to look up next strerror_r\n"); + err = dlerror(); + if (err) + fprintf(stderr, "%s\n", err); + abort(); + } + + //fprintf(stderr, "next strerror_r at %p\n", libc_strerror_r); + +#if 0 + libc_xpg_strerror_r = dlsym(RTLD_NEXT,"xpg_strerror_r"); + if (!libc_xpg_strerror_r) { + fprintf(stderr, "Failed to look up next xpg_strerror_r\n"); + err = dlerror(); + if (err) + fprintf(stderr, "%s\n", err); + abort(); + } + + //fprintf(stderr, "next xpg_strerror_r at %p\n", libc_xpg_strerror_r); +#endif + +} /* end error_init() */ + +/*****************************************************************************/ +/* + * overload glibc's strerror_r() with a version that knows about key errors + */ +char *strerror_r(int errnum, char *buf, size_t n) +{ + const char *errstr; + int len; + + printf("hello\n"); + + if (!error_inited) + error_init(); + + switch (errnum) { + case ENOKEY: + errstr = "Requested key not available"; + break; + + case EKEYEXPIRED: + errstr = "Key has expired"; + break; + + case EKEYREVOKED: + errstr = "Key has been revoked"; + break; + + case EKEYREJECTED: + errstr = "Key was rejected by service"; + break; + + default: + return libc_strerror_r(errnum, buf, n); + } + + len = strlen(errstr) + 1; + if (n > len) { + errno = ERANGE; + if (n > 0) { + memcpy(buf, errstr, n - 1); + buf[n - 1] = 0; + } + return NULL; + } + else { + memcpy(buf, errstr, len); + return buf; + } + +} /* end strerror_r() */ + +#if 0 +/*****************************************************************************/ +/* + * overload glibc's strerror_r() with a version that knows about key errors + */ +int xpg_strerror_r(int errnum, char *buf, size_t n) +{ + const char *errstr; + int len; + + if (!error_inited) + error_init(); + + switch (errnum) { + case ENOKEY: + errstr = "Requested key not available"; + break; + + case EKEYEXPIRED: + errstr = "Key has expired"; + break; + + case EKEYREVOKED: + errstr = "Key has been revoked"; + break; + + case EKEYREJECTED: + errstr = "Key was rejected by service"; + break; + + default: + return libc_xpg_strerror_r(errnum, buf, n); + } + + len = strlen(errstr) + 1; + if (n > len) { + errno = ERANGE; + if (n > 0) { + memcpy(buf, errstr, n - 1); + buf[n - 1] = 0; + } + return -1; + } + else { + memcpy(buf, errstr, len); + return 0; + } + +} /* end xpg_strerror_r() */ +#endif + +/*****************************************************************************/ +/* + * + */ +void perror(const char *msg) +{ + if (!error_inited) + error_init(); + + switch (errno) { + case ENOKEY: + fprintf(stderr, "%s: Requested key not available\n", msg); + return; + + case EKEYEXPIRED: + fprintf(stderr, "%s: Key has expired\n", msg); + return; + + case EKEYREVOKED: + fprintf(stderr, "%s: Key has been revoked\n", msg); + return; + + case EKEYREJECTED: + fprintf(stderr, "%s: Key was rejected by service\n", msg); + return; + + default: + libc_perror(msg); + return; + } + +} /* end perror() */ +#endif diff --git a/keyutils.h b/keyutils.h new file mode 100644 index 0000000000..887cbf280a --- /dev/null +++ b/keyutils.h @@ -0,0 +1,269 @@ +/* keyutils.h: key utility library interface + * + * Copyright (C) 2005,2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef KEYUTILS_H +#define KEYUTILS_H + +#include +#include + +extern const char keyutils_version_string[]; +extern const char keyutils_build_string[]; + +/* key serial number */ +typedef int32_t key_serial_t; + +/* special process keyring shortcut IDs */ +#define KEY_SPEC_THREAD_KEYRING -1 /* - key ID for thread-specific keyring */ +#define KEY_SPEC_PROCESS_KEYRING -2 /* - key ID for process-specific keyring */ +#define KEY_SPEC_SESSION_KEYRING -3 /* - key ID for session-specific keyring */ +#define KEY_SPEC_USER_KEYRING -4 /* - key ID for UID-specific keyring */ +#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ +#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ +#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */ + +/* request-key default keyrings */ +#define KEY_REQKEY_DEFL_NO_CHANGE -1 +#define KEY_REQKEY_DEFL_DEFAULT 0 +#define KEY_REQKEY_DEFL_THREAD_KEYRING 1 +#define KEY_REQKEY_DEFL_PROCESS_KEYRING 2 +#define KEY_REQKEY_DEFL_SESSION_KEYRING 3 +#define KEY_REQKEY_DEFL_USER_KEYRING 4 +#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 +#define KEY_REQKEY_DEFL_GROUP_KEYRING 6 + +/* key handle permissions mask */ +typedef uint32_t key_perm_t; + +#define KEY_POS_VIEW 0x01000000 /* possessor can view a key's attributes */ +#define KEY_POS_READ 0x02000000 /* possessor can read key payload / view keyring */ +#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */ +#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */ +#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */ +#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */ +#define KEY_POS_ALL 0x3f000000 + +#define KEY_USR_VIEW 0x00010000 /* user permissions... */ +#define KEY_USR_READ 0x00020000 +#define KEY_USR_WRITE 0x00040000 +#define KEY_USR_SEARCH 0x00080000 +#define KEY_USR_LINK 0x00100000 +#define KEY_USR_SETATTR 0x00200000 +#define KEY_USR_ALL 0x003f0000 + +#define KEY_GRP_VIEW 0x00000100 /* group permissions... */ +#define KEY_GRP_READ 0x00000200 +#define KEY_GRP_WRITE 0x00000400 +#define KEY_GRP_SEARCH 0x00000800 +#define KEY_GRP_LINK 0x00001000 +#define KEY_GRP_SETATTR 0x00002000 +#define KEY_GRP_ALL 0x00003f00 + +#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */ +#define KEY_OTH_READ 0x00000002 +#define KEY_OTH_WRITE 0x00000004 +#define KEY_OTH_SEARCH 0x00000008 +#define KEY_OTH_LINK 0x00000010 +#define KEY_OTH_SETATTR 0x00000020 +#define KEY_OTH_ALL 0x0000003f + +/* keyctl commands */ +#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */ +#define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */ +#define KEYCTL_UPDATE 2 /* update a key */ +#define KEYCTL_REVOKE 3 /* revoke a key */ +#define KEYCTL_CHOWN 4 /* set ownership of a key */ +#define KEYCTL_SETPERM 5 /* set perms on a key */ +#define KEYCTL_DESCRIBE 6 /* describe a key */ +#define KEYCTL_CLEAR 7 /* clear contents of a keyring */ +#define KEYCTL_LINK 8 /* link a key into a keyring */ +#define KEYCTL_UNLINK 9 /* unlink a key from a keyring */ +#define KEYCTL_SEARCH 10 /* search for a key in a keyring */ +#define KEYCTL_READ 11 /* read a key or keyring's contents */ +#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */ +#define KEYCTL_NEGATE 13 /* negate a partially constructed key */ +#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */ +#define KEYCTL_SET_TIMEOUT 15 /* set timeout on a key */ +#define KEYCTL_ASSUME_AUTHORITY 16 /* assume authority to instantiate key */ +#define KEYCTL_GET_SECURITY 17 /* get key security label */ +#define KEYCTL_SESSION_TO_PARENT 18 /* set my session keyring on my parent process */ +#define KEYCTL_REJECT 19 /* reject a partially constructed key */ +#define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */ +#define KEYCTL_INVALIDATE 21 /* invalidate a key */ +#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ +#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */ +#define KEYCTL_PKEY_QUERY 24 /* Query public key parameters */ +#define KEYCTL_PKEY_ENCRYPT 25 /* Encrypt a blob using a public key */ +#define KEYCTL_PKEY_DECRYPT 26 /* Decrypt a blob using a public key */ +#define KEYCTL_PKEY_SIGN 27 /* Create a public key signature */ +#define KEYCTL_PKEY_VERIFY 28 /* Verify a public key signature */ +#define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ +#define KEYCTL_MOVE 30 /* Move keys between keyrings */ +#define KEYCTL_CAPABILITIES 31 /* Find capabilities of keyrings subsystem */ + +/* keyctl structures */ +struct keyctl_dh_params { + key_serial_t priv; + key_serial_t prime; + key_serial_t base; +}; + +struct keyctl_kdf_params { + char *hashname; + char *otherinfo; + uint32_t otherinfolen; + uint32_t __spare[8]; +}; + +#define KEYCTL_SUPPORTS_ENCRYPT 0x01 +#define KEYCTL_SUPPORTS_DECRYPT 0x02 +#define KEYCTL_SUPPORTS_SIGN 0x04 +#define KEYCTL_SUPPORTS_VERIFY 0x08 + +struct keyctl_pkey_query { + unsigned int supported_ops; /* Which ops are supported */ + unsigned int key_size; /* Size of the key in bits */ + unsigned short max_data_size; /* Maximum size of raw data to sign in bytes */ + unsigned short max_sig_size; /* Maximum size of signature in bytes */ + unsigned short max_enc_size; /* Maximum size of encrypted blob in bytes */ + unsigned short max_dec_size; /* Maximum size of decrypted blob in bytes */ + unsigned int __spare[10]; +}; + +struct keyctl_pkey_params { + key_serial_t key_id; /* Serial no. of public key to use */ + unsigned int in_len; /* Input data size */ + union { + unsigned int out_len; /* Output buffer size (encrypt/decrypt/sign) */ + unsigned int in2_len; /* Second input data size (verify) */ + }; + unsigned int __spare[7]; +}; + +#define KEYCTL_MOVE_EXCL 0x00000001 /* Do not displace from the to-keyring */ + +/* + * Capabilities flags. The capabilities list is an array of 8-bit integers; + * each integer can carry up to 8 flags. + */ +#define KEYCTL_CAPS0_CAPABILITIES 0x01 /* KEYCTL_CAPABILITIES supported */ +#define KEYCTL_CAPS0_PERSISTENT_KEYRINGS 0x02 /* Persistent keyrings enabled */ +#define KEYCTL_CAPS0_DIFFIE_HELLMAN 0x04 /* Diffie-Hellman ops enabled */ +#define KEYCTL_CAPS0_PUBLIC_KEY 0x08 /* Public key ops enabled */ +#define KEYCTL_CAPS0_BIG_KEY 0x10 /* big_key-type enabled */ +#define KEYCTL_CAPS0_INVALIDATE 0x20 /* KEYCTL_INVALIDATE supported */ +#define KEYCTL_CAPS0_RESTRICT_KEYRING 0x40 /* KEYCTL_RESTRICT_KEYRING supported */ +#define KEYCTL_CAPS0_MOVE 0x80 /* KEYCTL_MOVE supported */ + +/* + * syscall wrappers + */ +extern key_serial_t add_key(const char *type, + const char *description, + const void *payload, + size_t plen, + key_serial_t ringid); + +extern key_serial_t request_key(const char *type, + const char *description, + const char *callout_info, + key_serial_t destringid); + +extern long keyctl(int cmd, ...); + +/* + * keyctl function wrappers + */ +extern key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create); +extern key_serial_t keyctl_join_session_keyring(const char *name); +extern long keyctl_update(key_serial_t id, const void *payload, size_t plen); +extern long keyctl_revoke(key_serial_t id); +extern long keyctl_chown(key_serial_t id, uid_t uid, gid_t gid); +extern long keyctl_setperm(key_serial_t id, key_perm_t perm); +extern long keyctl_describe(key_serial_t id, char *buffer, size_t buflen); +extern long keyctl_clear(key_serial_t ringid); +extern long keyctl_link(key_serial_t id, key_serial_t ringid); +extern long keyctl_unlink(key_serial_t id, key_serial_t ringid); +extern long keyctl_search(key_serial_t ringid, + const char *type, + const char *description, + key_serial_t destringid); +extern long keyctl_read(key_serial_t id, char *buffer, size_t buflen); +extern long keyctl_instantiate(key_serial_t id, + const void *payload, + size_t plen, + key_serial_t ringid); +extern long keyctl_negate(key_serial_t id, unsigned timeout, key_serial_t ringid); +extern long keyctl_set_reqkey_keyring(int reqkey_defl); +extern long keyctl_set_timeout(key_serial_t key, unsigned timeout); +extern long keyctl_assume_authority(key_serial_t key); +extern long keyctl_get_security(key_serial_t key, char *buffer, size_t buflen); +extern long keyctl_session_to_parent(void); +extern long keyctl_reject(key_serial_t id, unsigned timeout, unsigned error, + key_serial_t ringid); +struct iovec; +extern long keyctl_instantiate_iov(key_serial_t id, + const struct iovec *payload_iov, + unsigned ioc, + key_serial_t ringid); +extern long keyctl_invalidate(key_serial_t id); +extern long keyctl_get_persistent(uid_t uid, key_serial_t id); +extern long keyctl_dh_compute(key_serial_t priv, key_serial_t prime, + key_serial_t base, char *buffer, size_t buflen); +extern long keyctl_dh_compute_kdf(key_serial_t private, key_serial_t prime, + key_serial_t base, char *hashname, + char *otherinfo, size_t otherinfolen, + char *buffer, size_t buflen); +extern long keyctl_restrict_keyring(key_serial_t keyring, const char *type, + const char *restriction); + +extern long keyctl_pkey_query(key_serial_t key_id, + const char *info, + struct keyctl_pkey_query *result); +extern long keyctl_pkey_encrypt(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + void *enc, size_t enc_len); +extern long keyctl_pkey_decrypt(key_serial_t key_id, + const char *info, + const void *enc, size_t enc_len, + void *data, size_t data_len); +extern long keyctl_pkey_sign(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + void *sig, size_t sig_len); +extern long keyctl_pkey_verify(key_serial_t key_id, + const char *info, + const void *data, size_t data_len, + const void *sig, size_t sig_len); +extern long keyctl_move(key_serial_t id, + key_serial_t from_ringid, + key_serial_t to_ringid, + unsigned int flags); +extern long keyctl_capabilities(unsigned char *buffer, size_t buflen); + +/* + * utilities + */ +extern int keyctl_describe_alloc(key_serial_t id, char **_buffer); +extern int keyctl_read_alloc(key_serial_t id, void **_buffer); +extern int keyctl_get_security_alloc(key_serial_t id, char **_buffer); +extern int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime, + key_serial_t base, void **_buffer); + +typedef int (*recursive_key_scanner_t)(key_serial_t parent, key_serial_t key, + char *desc, int desc_len, void *data); +extern int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data); +extern int recursive_session_key_scan(recursive_key_scanner_t func, void *data); +extern key_serial_t find_key_by_type_and_desc(const char *type, const char *desc, + key_serial_t destringid); + +#endif /* KEYUTILS_H */ diff --git a/keyutils.spec b/keyutils.spec new file mode 100644 index 0000000000..6bf7df3c07 --- /dev/null +++ b/keyutils.spec @@ -0,0 +1,302 @@ +%define vermajor 1 +%define verminor 6.1 +%define version %{vermajor}.%{verminor} +%define libapivermajor 1 +%define libapiversion %{libapivermajor}.9 + +# % define buildid .local + +Name: keyutils +Version: %{version} +Release: 1%{?buildid}%{?dist} +Summary: Linux Key Management Utilities +License: GPLv2+ and LGPLv2+ +Url: http://people.redhat.com/~dhowells/keyutils/ + +Source0: http://people.redhat.com/~dhowells/keyutils/keyutils-%{version}.tar.bz2 + +BuildRequires: gcc +BuildRequires: glibc-kernheaders >= 2.4-9.1.92 +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description +Utilities to control the kernel key management facility and to provide +a mechanism by which the kernel call back to user space to get a key +instantiated. + +%package libs +Summary: Key utilities library + +%description libs +This package provides a wrapper library for the key management facility system +calls. + +%package libs-devel +Summary: Development package for building Linux key management utilities +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description libs-devel +This package provides headers and libraries for building key utilities. + +%prep +%setup -q + +%define datadir %{_datarootdir}/keyutils + +%build +make \ + NO_ARLIB=1 \ + ETCDIR=%{_sysconfdir} \ + LIBDIR=%{_libdir} \ + USRLIBDIR=%{_libdir} \ + BINDIR=%{_bindir} \ + SBINDIR=%{_sbindir} \ + MANDIR=%{_mandir} \ + INCLUDEDIR=%{_includedir} \ + SHAREDIR=%{datadir} \ + RELEASE=.%{release} \ + NO_GLIBC_KEYERR=1 \ + CFLAGS="-Wall $RPM_OPT_FLAGS -Werror" \ + LDFLAGS="%{?__global_ldflags}" + +%install +make \ + NO_ARLIB=1 \ + DESTDIR=$RPM_BUILD_ROOT \ + ETCDIR=%{_sysconfdir} \ + LIBDIR=%{_libdir} \ + USRLIBDIR=%{_libdir} \ + BINDIR=%{_bindir} \ + SBINDIR=%{_sbindir} \ + MANDIR=%{_mandir} \ + INCLUDEDIR=%{_includedir} \ + SHAREDIR=%{datadir} \ + install + +%ldconfig_scriptlets libs + +%files +%doc README +%license LICENCE.GPL +%{_sbindir}/* +%{_bindir}/* +%{datadir} +%{_mandir}/man1/* +%{_mandir}/man5/* +%{_mandir}/man8/* +%config(noreplace) %{_sysconfdir}/* + +%files libs +%license LICENCE.LGPL +%{_mandir}/man7/* +%{_libdir}/libkeyutils.so.%{libapiversion} +%{_libdir}/libkeyutils.so.%{libapivermajor} + +%files libs-devel +%{_libdir}/libkeyutils.so +%{_includedir}/* +%{_mandir}/man3/* +%{_libdir}/pkgconfig/libkeyutils.pc + +%changelog +* Fri Aug 2 2019 David Howells - 1.6.1-1 +- Add support for keyctl_move(). +- Add support for keyctl_capabilities(). +- Make key=val list optional for various public-key ops. +- Fix system call signature for KEYCTL_PKEY_QUERY. +- Fix 'keyctl pkey_query' argument passing. +- Use keyctl_read_alloc() in dump_key_tree_aux(). +- Various manual page fixes. + +* Tue Nov 13 2018 David Howells - 1.6-1 +- Apply various specfile cleanups from Fedora. +- request-key: Provide a command line option to suppress helper execution. +- request-key: Find least-wildcard match rather than first match. +- Remove the dependency on MIT Kerberos. +- Fix some error messages +- keyctl_dh_compute.3: Suggest /proc/crypto for list of available hashes. +- Fix doc and comment typos. +- Add public key ops for encrypt, decrypt, sign and verify (needs linux-4.20). +- Add pkg-config support for finding libkeyutils. + +* Wed May 9 2018 David Howells - 1.5.11-1 +- Add keyring restriction support. +- Add KDF support to the Diffie-Helman function. +- DNS: Add support for AFS config files and SRV records + +* Wed Mar 15 2017 David Howells - 1.5.10-1 +- Include sys/types.h in keyutils.h. +- The dns resolver needs limits.h. +- Overhaul of all manual pages. +- Some manual pages moved to Linux man-pages project. +- Add Diffie-Helman keyctl function. + +* Fri Feb 21 2014 David Howells - 1.5.9-1 +- Add manpages for get_persistent. +- Fix memory leaks in keyctl_describe/read/get_security_alloc(). +- Use keyctl_describe_alloc in dump_key_tree_aux rather than open coding it. +- Exit rather than returning from act_xxx() functions. +- Fix memory leak in dump_key_tree_aux. +- Only get the groups list if we need it. +- Don't trust sscanf's %%n argument. +- Use the correct path macros in the specfile. +- Avoid use realloc when the memory has no content. +- Fix a bunch of issues in key.dns_resolver. +- Fix command table searching in keyctl utility. +- Fix a typo in the permissions mask constants. +- Improve the keyctl_read manpage. +- Add man7 pages describing various keyrings concepts. + +* Fri Oct 4 2013 David Howells - 1.5.8-1 +- New lib symbols should go in a new library minor version. + +* Wed Oct 2 2013 David Howells - 1.5.7-1 +- Provide a utility function to find a key by type and name. +- Allow keyctl commands to take a type+name arg instead of a key-id arg. +- Add per-UID get_persistent keyring function. + +* Thu Aug 29 2013 David Howells - 1.5.6-1 +- Fix the request-key.conf.5 manpage. +- Fix the max depth of key tree dump (keyctl show). +- The input buffer size for keyctl padd and pinstantiate should be larger. +- Add keyctl_invalidate.3 manpage. + +* Wed Nov 30 2011 David Howells - 1.5.5-1 +- Fix a Makefile error. + +* Wed Nov 30 2011 David Howells - 1.5.4-1 +- Fix the keyctl padd command and similar to handle binary input. +- Make keyctl show able to take a keyring to dump. +- Make keyctl show able to take a flag to request hex key IDs. +- Make keyctl show print the real ID of the root keyring. + +* Tue Nov 15 2011 David Howells +- Allow /sbin/request-key to have multiple config files. + +* Wed Aug 31 2011 David Howells +- Adjust the manual page for 'keyctl unlink' to show keyring is optional. +- Add --version support for the keyutils version and build date. + +* Thu Aug 11 2011 David Howells - 1.5.3-1 +- Make the keyutils rpm depend on the same keyutils-libs rpm version. + +* Tue Jul 26 2011 David Howells - 1.5.2-1 +- Use correct format spec for printing pointer subtraction results. + +* Tue Jul 19 2011 David Howells - 1.5.1-1 +- Fix unread variables. +- Licence file update. + +* Thu Mar 10 2011 David Howells - 1.5-1 +- Disable RPATH setting in Makefile. +- Add -I. to build to get this keyutils.h. +- Make CFLAGS override on make command line work right. +- Make specfile UTF-8. +- Support KEYCTL_REJECT. +- Support KEYCTL_INSTANTIATE_IOV. +- Add AFSDB DNS lookup program from Wang Lei. +- Generalise DNS lookup program. +- Add recursive scan utility function. +- Add bad key reap command to keyctl. +- Add multi-unlink variant to keyctl unlink command. +- Add multi key purge command to keyctl. +- Handle multi-line commands in keyctl command table. +- Move the package to version to 1.5. + +* Tue Mar 1 2011 David Howells - 1.4-4 +- Make build guess at default libdirs and word size. +- Make program build depend on library in Makefile. +- Don't include $(DESTDIR) in MAN* macros. +- Remove NO_GLIBC_KEYSYS as it is obsolete. +- Have Makefile extract version info from specfile and version script. +- Provide RPM build rule in Makefile. +- Provide distclean rule in Makefile. + +* Fri Dec 17 2010 Diego Elio Pettenò - 1.4-3 +- Fix local linking and RPATH. + +* Thu Jun 10 2010 David Howells - 1.4-2 +- Fix prototypes in manual pages (some char* should be void*). +- Rename the keyctl_security.3 manpage to keyctl_get_security.3. + +* Fri Mar 19 2010 David Howells - 1.4-1 +- Fix the library naming wrt the version. +- Move the package to version to 1.4. + +* Fri Mar 19 2010 David Howells - 1.3-3 +- Fix spelling mistakes in manpages. +- Add an index manpage for all the keyctl functions. + +* Thu Mar 11 2010 David Howells - 1.3-2 +- Fix rpmlint warnings. + +* Fri Feb 26 2010 David Howells - 1.3-1 +- Fix compiler warnings in request-key. +- Expose the kernel function to get a key's security context. +- Expose the kernel function to set a processes keyring onto its parent. +- Move libkeyutils library version to 1.3. + +* Tue Aug 22 2006 David Howells - 1.2-1 +- Remove syscall manual pages (section 2) to man-pages package [BZ 203582] +- Don't write to serial port in debugging script + +* Mon Jun 5 2006 David Howells - 1.1-4 +- Call ldconfig during (un)installation. + +* Fri May 5 2006 David Howells - 1.1-3 +- Don't include the release number in the shared library filename +- Don't build static library + +* Fri May 5 2006 David Howells - 1.1-2 +- More bug fixes from Fedora reviewer. + +* Thu May 4 2006 David Howells - 1.1-1 +- Fix rpmlint errors + +* Mon Dec 5 2005 David Howells - 1.0-2 +- Add build dependency on glibc-kernheaders with key management syscall numbers + +* Tue Nov 29 2005 David Howells - 1.0-1 +- Add data pipe-in facility for keyctl request2 + +* Mon Nov 28 2005 David Howells - 1.0-1 +- Rename library and header file "keyutil" -> "keyutils" for consistency +- Fix shared library version naming to same way as glibc. +- Add versioning for shared library symbols +- Create new keyutils-libs package and install library and main symlink there +- Install base library symlink in /usr/lib and place in devel package +- Added a keyutils archive library +- Shorten displayed key permissions list to just those we actually have + +* Thu Nov 24 2005 David Howells - 0.3-4 +- Add data pipe-in facilities for keyctl add, update and instantiate + +* Fri Nov 18 2005 David Howells - 0.3-3 +- Added stdint.h inclusion in keyutils.h +- Made request-key.c use request_key() rather than keyctl_search() +- Added piping facility to request-key + +* Thu Nov 17 2005 David Howells - 0.3-2 +- Added timeout keyctl option +- request_key auth keys must now be assumed +- Fix keyctl argument ordering for debug negate line in request-key.conf + +* Thu Jul 28 2005 David Howells - 0.3-1 +- Must invoke initialisation from perror() override in libkeyutils +- Minor UI changes + +* Wed Jul 20 2005 David Howells - 0.2-2 +- Bump version to permit building in main repositories. + +* Tue Jul 12 2005 David Howells - 0.2-1 +- Don't attempt to define the error codes in the header file. +- Pass the release ID through to the makefile to affect the shared library name. + +* Tue Jul 12 2005 David Howells - 0.1-3 +- Build in the perror() override to get the key error strings displayed. + +* Tue Jul 12 2005 David Howells - 0.1-2 +- Need a defattr directive after each files directive. + +* Tue Jul 12 2005 David Howells - 0.1-1 +- Package creation. diff --git a/libkeyutils.pc.in b/libkeyutils.pc.in new file mode 100644 index 0000000000..4c062677c7 --- /dev/null +++ b/libkeyutils.pc.in @@ -0,0 +1,8 @@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libkeyutils +Description: keyutils library +Version: @VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lkeyutils diff --git a/man/asymmetric-key.7 b/man/asymmetric-key.7 new file mode 100644 index 0000000000..5fc78cb057 --- /dev/null +++ b/man/asymmetric-key.7 @@ -0,0 +1,232 @@ +.\" +.\" Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH ASYMMETRIC-KEY 7 "8 Nov 2018" Linux "Asymmetric Kernel Key Type" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +asymmetric \- Kernel key type for holding asymmetric keys +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH OVERVIEW +.PP +A kernel key of +.B asymmetric +type acts as a handle to an asymmetric key as used for public-key +cryptography. The key material itself may be held inside the kernel or it may +be held in hardware with operations being offloaded. This prevents direct +user access to the cryptographic material. +.PP +Keys may be any asymmetric type (RSA, ECDSA, ...) and may have both private and +public components present or just the public component. +.PP +Asymmetric keys can be made use of by both the kernel and userspace. The +kernel can make use of them for module signature verification and kexec image +verification for example. Userspace is provided with a set of +.BR keyctl ( KEYCTL_PKEY_* ) +calls for querying and using the key. These are wrapped by +.B libkeyutils +as functions named +.BR keyctl_pkey_*() . +.PP +An asymmetric-type key can be loaded by the keyctl utility using a command +line like: +.PP +.in +4n +.EX +openssl x509 -in key.x509 -outform DER | +keyctl padd asymmetric foo @s +.EE +.in +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.PP +The asymmetric-type key can be viewed as a container that comprises of a +number of components: +.TP +Parsers +The asymmetric key parsers attempt to identify the content of the payload blob +and extract useful data from it with which to instantiate the key. The parser +is only used when adding, instantiating or updating a key and isn't thereafter +associated with the key. +.IP +Available parsers include ones that can deal with +.RB "DER-encoded " X.509 ", DER-encoded " PKCS#8 " and DER-encoded " TPM "-wrapped blobs." +.TP +Public and private keys +These are the cryptographic components of the key pair. The public half +should always be available, but the private half might not be. What +operations are available can be queried, as can the size of the key. The key +material may or may not actually reside in the kernel. +.TP +Identifiers +In addition to the normal key description (which can be generated by the +parser), a number of supplementary identifiers may be available that can be +searched for. These may be obtained, for example, by hashing the public key +material or from the subjectKeyIdentifier in an X.509 certificate. +.IP +Identifier-based searches are selected by passing as the description to +.BR keyctl_search () +a string constructed of hex characters prefixed with either "id:" or "ex:". +The "id:" prefix indicates that a partial tail match is permissible whereas +"ex:" requires an exact match on the full string. The hex characters indicate +the data to match. +.TP +Subtype +This is the driver inside the kernel that accesses the key material and +performs operations on it. It might be entirely software-based or it may +offload the operations to a hardware key store, such as a +.BR TPM . +.PP +Note that expiry times from the payload are ignored as these patches may be +used during boot before the system clock is set. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH PARSERS +.PP +The asymmetric key parsers can handle keys in a number of forms: +.TP +\fBX.509\fP +DER-encoded X.509 certificates can be accepted. Two identifiers are +constructed: one from from the certificate issuer and serial number and the +other from the subjectKeyIdentifier, if present. If left blank, the key +description will be filled in from the subject field plus either the +subjectKeyIdentifier or the serialNumber. Only the public key is filled in +and only the encrypt and verify operations are supported. +.IP +The signature on the X.509 certificate may be checked by the keyring it is +being added to and it may also be rejected if the key is blacklisted. +.TP +\fBPKCS#8\fP +Unencrypted DER-encoded PKCS#8 key data containers can be accepted. Currently +no identifiers are constructed. The private key and the public key are loaded +from the PKCS#8 blobs. Encrypted PKCS#8 is not currently supported. +.TP +\fBTPM-Wrapped keys\fP +DER-encoded TPM-wrapped TSS key blobs can be accepted. Currently no +identifiers are constructed. The public key is extracted from the blob but +the private key is expected to be resident in the TPM. Encryption and +signature verification is done in software, but decryption and signing are +offloaded to the TPM so as not to expose the private key. +.IP +This parser only supports TPM-1.2 wrappings and enc=pkcs1 encoding type. It +also uses a hard-coded null SRK password; password-protected SRKs are not yet +supported. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH USERSPACE API +.PP +In addition to the standard keyutils library functions, such as +.IR keyctl_update (), +there are five calls specific to the asymmetric key type (though they are open +to being used by other key types also): +.PP +.RS +\fIkeyctl_pkey_query\fP() +.br +\fIkeyctl_pkey_encrypt\fP() +.br +\fIkeyctl_pkey_decrypt\fP() +.br +\fIkeyctl_pkey_sign\fP() +.br +\fIkeyctl_pkey_verify\fP() +.RE +.PP +The query function can be used to retrieve information about an asymmetric key, +such as the key size, the amount of space required by buffers for the other +operations and which operations are actually supported. +.PP +The other operations form two pairs: encrypt/decrypt and create/verify +signature. Not all of these operations will necessarily be available; +typically, encrypt and verify only require the public key to be available +whereas decrypt and sign require the private key as well. +.PP +All of these operations take an information string parameter that supplies +additional information such as encoding type/form and the password(s) needed to +unlock/unwrap the key. This takes the form of a comma-separated list of +"key[=value]" pairs, the exact set of which depends on the subtype driver used +by a particular key. +.PP +Available parameters include: +.TP +enc= +The encoding type for use in an encrypted blob or a signature. An example +might be "enc=pkcs1". +.TP +hash= +The name of the hash algorithm that was used to digest the data to be signed. +Note that this is only used to construct any encoding that is used in a +signature. The data to be signed or verified must have been parsed by the +caller and the hash passed to \fIkeyctl_pkey_sign\fP() or +\fIkeyctl_pkey_verify\fP() beforehand. An example might be "hash=sha256". +.PP +Note that not all parameters are used by all subtypes. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RESTRICTED KEYRINGS +.PP +An additional keyutils function, +.IR keyctl_restrict_keyring (), +can be used to gate a keyring so that a new key can only be added to the +affected keyring if (a) it's an asymmetric key, (b) it's validly signed by a +key in some appropriate keyring and (c) it's not blacklisted. +.PP +.in +4n +.EX + keyctl_restrict_keyring(keyring, "asymmetric", + "key_or_keyring:[:chain]"); +.EE +.in +.PP +Where \fI\fP is the ID of a key or a ring of keys that act as the +authority to permit a new key to be added to the keyring. The \fIchain\fP flag +indicates that keys that have been added to the keyring may also be used to +verify new keys. Authorising keys must themselves be asymmetric-type keys that +can be used to do a signature verification on the key being added. +.PP +Note that there are various system keyrings visible to the root user that may +permit additional keys to be added. These are typically gated by keys that +already exist, preventing unauthorised keys from being used for such things as +module verification. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH BLACKLISTING +.PP +When the attempt is made to add a key to the kernel, a hash of the public key +is checked against the +.BR blacklist. +This is a system keyring named +.B .blacklist +and contains keys of type +.BR blacklist . +If the blacklist contains a key whose description matches the hash of the new +key, that new key will be rejected with error +.BR EKEYREJECTED . +.PP +The blacklist keyring may be loaded from multiple sources, including a list +compiled into the kernel and the UEFI +.B dbx +variable. Further hashes may also be blacklisted by the administrator. Note +that blacklisting is not retroactive, so an asymmetric key that is already on +the system cannot be blacklisted by adding a matching blacklist entry later. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH VERSIONS +The +.B asymmetric +key type first appeared in v3.7 of the Linux kernel, the +.B restriction +function in v4.11 and the +.B public key operations +in v4.20. +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (3), +.BR keyctl_pkey_encrypt (3), +.BR keyctl_pkey_query (3), +.BR keyctl_pkey_sign (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/find_key_by_type_and_name.3 b/man/find_key_by_type_and_name.3 new file mode 100644 index 0000000000..2fbd21e776 --- /dev/null +++ b/man/find_key_by_type_and_name.3 @@ -0,0 +1,65 @@ +.\" +.\" Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH FIND_KEY_BY_TYPE_AND_NAME 3 "10 Sep 2013" Linux "Linux Key Utility Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +find_key_by_type_and_name \- find a key by type and name +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "key_serial_t find_key_by_type_and_name(const char *" type , +.BI " const char *" description ", key_serial_t " destringid ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR find_key_by_type_and_name () +searches for a key with the given +.I type +and exact +.IR description , +firstly in the thread, process and session keyrings to which a process is +subscribed and secondly in +.IR /proc/keys . +.P +If a key is found, and +.I destringid +is not 0 and specifies a keyring, then the found key will be linked into it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +The function returns the ID of the key if a key was found or \-1 otherwise. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +No key was found or the keyring specified is invalid. +.TP +.B EKEYEXPIRED +The key or keyring have expired. +.TP +.B EKEYREVOKED +The key or keyring have been revoked. +.TP +.B EACCES +The key is not accessible or keyring exists, but is not +.B writable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7) diff --git a/man/key.dns_resolver.8 b/man/key.dns_resolver.8 new file mode 100644 index 0000000000..e1882e061f --- /dev/null +++ b/man/key.dns_resolver.8 @@ -0,0 +1,34 @@ +.\" +.\" Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEY.DNS_RESOLVER 8 "04 Mar 2011" Linux "Linux Key Management Utilities" +.SH NAME +key.dns_resolver \- upcall for request\-key to handle dns_resolver keys +.SH SYNOPSIS +\fB/sbin/key.dns_resolver \fR +.br +\fB/sbin/key.dns_resolver \fR\-D [\-v] [\-v] +.SH DESCRIPTION +This program is invoked by request\-key on behalf of the kernel when kernel +services (such as NFS, CIFS and AFS) want to perform a hostname lookup and the +kernel does not have the key cached. It is not ordinarily intended to be +called directly. +.P +It can be called in debugging mode to test its functionality by passing a +\fB\-D\fR flag on the command line. For this to work, the key description and +the callout information must be supplied. Verbosity can be increased by +supplying one or more \fB\-v\fR flags. +.SH ERRORS +All errors will be logged to the syslog. +.SH SEE ALSO +.ad l +.nh +.BR request\-key.conf (5), +.BR keyrings (7), +.BR request\-key (8) diff --git a/man/keyctl.1 b/man/keyctl.1 new file mode 100644 index 0000000000..1c8f56958a --- /dev/null +++ b/man/keyctl.1 @@ -0,0 +1,908 @@ +.\" +.\" Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL 1 "20 Feb 2014" Linux "Linux Key Management Utilities" +.SH NAME +keyctl \- key management facility control +.SH SYNOPSIS +\fBkeyctl\fR \-\-version +.br +\fBkeyctl\fR supports [] +.br +\fBkeyctl\fR show [\-x] [] +.br +\fBkeyctl\fR add +.br +\fBkeyctl\fR padd +.br +\fBkeyctl\fR request [] +.br +\fBkeyctl\fR request2 [] +.br +\fBkeyctl\fR prequest2 [] +.br +\fBkeyctl\fR update +.br +\fBkeyctl\fR pupdate +.br +\fBkeyctl\fR newring +.br +\fBkeyctl\fR revoke +.br +\fBkeyctl\fR clear +.br +\fBkeyctl\fR link +.br +\fBkeyctl\fR unlink [] +.br +\fBkeyctl\fR move [-f] +.br +\fBkeyctl\fR search [] +.br +\fBkeyctl\fR restrict_keyring [ []] +.br +\fBkeyctl\fR read +.br +\fBkeyctl\fR pipe +.br +\fBkeyctl\fR print +.br +\fBkeyctl\fR list +.br +\fBkeyctl\fR rlist +.br +\fBkeyctl\fR describe +.br +\fBkeyctl\fR rdescribe [sep] +.br +\fBkeyctl\fR chown +.br +\fBkeyctl\fR chgrp +.br +\fBkeyctl\fR setperm +.br +\fBkeyctl\fR new_session +.br +\fBkeyctl\fR session +.br +\fBkeyctl\fR session \- [ ...] +.br +\fBkeyctl\fR session [ ...] +.br +\fBkeyctl\fR instantiate +.br +\fBkeyctl\fR pinstantiate +.br +\fBkeyctl\fR negate +.br +\fBkeyctl\fR reject +.br +\fBkeyctl\fR timeout +.br +\fBkeyctl\fR security +.br +\fBkeyctl\fR reap [\-v] +.br +\fBkeyctl\fR purge +.br +\fBkeyctl\fR purge [\-i] [\-p] +.br +\fBkeyctl\fR purge \-s +.br +\fBkeyctl\fR get_persistent [] +.br +\fBkeyctl\fR dh_compute +.br +\fBkeyctl\fR dh_compute_kdf +.br +\fBkeyctl\fR dh_compute_kdf_oi +.br +\fBkeyctl\fR pkey_query [k=v]* +.br +\fBkeyctl\fR pkey_encrypt [k=v]* > +.br +\fBkeyctl\fR pkey_decrypt [k=v]* > +.br +\fBkeyctl\fR pkey_sign [k=v]* > +.br +\fBkeyctl\fR pkey_decrypt [k=v]* +.SH DESCRIPTION +This program is used to control the key management facility in various ways +using a variety of subcommands. +.SH KEY IDENTIFIERS +The key identifiers passed to or returned from keyctl are, in general, positive +integers. There are, however, some special values with special meanings that +can be passed as arguments: +.TP +No key: \fB0\fR +.TP +Thread keyring: \fB@t\fR or \fB\-1\fR +Each thread may have its own keyring. This is searched first, before all +others. The thread keyring is replaced by (v)fork, exec and clone. +.TP +Process keyring: \fB@p\fR or \fB\-2\fR +Each process (thread group) may have its own keyring. This is shared between +all members of a group and will be searched after the thread keyring. The +process keyring is replaced by (v)fork and exec. +.TP +Session keyring: \fB@s\fR or \fB\-3\fR +Each process subscribes to a session keyring that is inherited across (v)fork, +exec and clone. This is searched after the process keyring. Session keyrings +can be named and an extant keyring can be joined in place of a process's +current session keyring. +.TP +User specific keyring: \fB@u\fR or \fB\-4\fR +This keyring is shared between all the processes owned by a particular user. It +isn't searched directly, but is normally linked to from the session keyring. +.TP +User default session keyring: \fB@us\fR or \fB\-5\fR +This is the default session keyring for a particular user. Login processes that +change to a particular user will bind to this session until another session is +set. +.TP +Group specific keyring: \fB@g\fR or \fB\-6\fR +This is a place holder for a group specific keyring, but is not actually +implemented yet in the kernel. +.TP +Assumed request_key authorisation key: \fB@a\fR or \fB\-7\fR +This selects the authorisation key provided to the +.BR request_key () +helper to +permit it to access the callers keyrings and instantiate the target key. +.TP +Keyring by name: \fB%:\fR +A named keyring. This will be searched for in the process's keyrings and in +.IR /proc/keys . +.TP +Key by name: \fB%:\fR +A named key of the given type. This will be searched for in the process's +keyrings and in +.IR /proc/keys . +.SH COMMAND SYNTAX +Any non-ambiguous shortening of a command name may be used in lieu of the full +command name. This facility should not be used in scripting as new commands may +be added in future that then cause ambiguity. +.SS Display the package version number +\fBkeyctl \-\-version\fR + +This command prints the package version number and build date and exits: + +.RS +.nf +$ keyctl \-\-version +keyctl from keyutils\-1.5.3 (Built 2011\-08\-24) +.fi +.RE +.SS Query subsystem capabilities +\fBkeyctl\fR supports [] + +This command can list the available capabilities: + +.RS +.nf +$ keyctl supports +have_capabilities=0 +have_persistent_keyrings=1 +have_dh_compute=1 +have_public_key=1 +... +.fi +.RE +.P +And it can query a capability: + +.RS +.nf +$ keyctl supports pkey +echo $? +0 +.fi +.RE + +which returns 0 if the capability is supported, 1 if it isn't and 3 if the +name is not recognised. The capabilities supported are: +.TP +.B capabilities +The kernel supports capability querying. If not, the other capabilities will +be queried as best libkeyutils can manage. +.TP +.B persistent_keyrings +The kernel supports persistent keyrings. +.TP +.B dh_compute +The kernel supports Diffie-Hellman computation operations. +.TP +.B public_key +The kernel supports public key operations. +.TP +.B big_key_type +The kernel supports the big_key key type. +.TP +.B key_invalidate +The kernel supports the invalidate key operaiton. +.TP +.B restrict_keyring +The kernel supports the restrict_keyring operation. +.TP +.B move_key +The kernel supports the move key operation. + +.SS Show process keyrings +\fBkeyctl show [\-x] []\fR + +By default this command recursively shows what keyrings a process is subscribed +to and what keys and keyrings they contain. If a keyring is specified then +that keyring will be dumped instead. If \fB\-x\fR is specified then the keyring +IDs will be dumped in hex instead of decimal. +.SS Add a key to a keyring +\fBkeyctl add\fR +.br +\fBkeyctl padd\fR + +This command creates a key of the specified type and description; instantiates +it with the given data and attaches it to the specified keyring. It then prints +the new key's ID on stdout: + +.RS +.nf +$ keyctl add user mykey stuff @u +26 +.fi +.RE + +The \fBpadd\fR variant of the command reads the data from stdin rather than +taking it from the command line: + +.RS +.fi +$ echo \-n stuff | keyctl padd user mykey @u +26 +.fi +.RE +.SS Request a key +\fBkeyctl request\fR [] +.br +\fBkeyctl request2\fR [] +.br +\fBkeyctl prequest2\fR [] + +These three commands request the lookup of a key of the given type and +description. The process's keyrings will be searched, and if a match is found +the matching key's ID will be printed to stdout; and if a destination keyring +is given, the key will be added to that keyring also. + +If there is no key, the first command will simply return the error ENOKEY and +fail. The second and third commands will create a partial key with the type and +description, and call out to +.IR /sbin/request\-key +with that key and the +extra information supplied. This will then attempt to instantiate the key in +some manner, such that a valid key is obtained. + +The third command is like the second, except that the callout information is +read from stdin rather than being passed on the command line. + +If a valid key is obtained, the ID will be printed and the key attached as if +the original search had succeeded. + +If there wasn't a valid key obtained, a temporary negative key will be attached +to the destination keyring if given and the error "Requested key not available" +will be given. + +.RS +.nf +$ keyctl request2 user debug:hello wibble +23 +$ echo \-n wibble | keyctl prequest2 user debug:hello +23 +$ keyctl request user debug:hello +23 +.fi +.RE +.SS Update a key +\fBkeyctl update\fR +.br +\fBkeyctl pupdate\fR + +This command replaces the data attached to a key with a new set of data. If the +type of the key doesn't support update then error "Operation not supported" +will be returned. + +.RS +.nf +$ keyctl update 23 zebra +.fi +.RE + +The \fBpupdate\fR variant of the command reads the data from stdin rather than +taking it from the command line: + +.RS +.nf +$ echo \-n zebra | keyctl pupdate 23 +.fi +.RE +.SS Create a keyring +\fBkeyctl newring\fR + +This command creates a new keyring of the specified name and attaches it to the +specified keyring. The ID of the new keyring will be printed to stdout if +successful. + +.RS +.nf +$ keyctl newring squelch @us +27 +.fi +.RE +.SS Revoke a key +\fBkeyctl revoke\fR + +This command marks a key as being revoked. Any further operations on that key +(apart from unlinking it) will return error "Key has been revoked". + +.RS +.nf +$ keyctl revoke 26 +$ keyctl describe 26 +keyctl_describe: Key has been revoked +.fi +.RE +.SS Clear a keyring +\fBkeyctl clear\fR + +This command unlinks all the keys attached to the specified keyring. Error +"Not a directory" will be returned if the key specified is not a keyring. + +.RS +.nf +$ keyctl clear 27 +.fi +.RE +.SS Link a key to a keyring +\fBkeyctl link\fR + +This command makes a link from the key to the keyring if there's enough +capacity to do so. Error "Not a directory" will be returned if the destination +is not a keyring. Error "Permission denied" will be returned if the key doesn't +have link permission or the keyring doesn't have write permission. Error "File +table overflow" will be returned if the keyring is full. Error "Resource +deadlock avoided" will be returned if an attempt was made to introduce a +recursive link. + +.RS +.nf +$ keyctl link 23 27 +$ keyctl link 27 27 +keyctl_link: Resource deadlock avoided +.fi +.RE +.SS Unlink a key from a keyring or the session keyring tree +\fBkeyctl unlink\fR [] + +If the keyring is specified, this command removes a link to the key from the +keyring. Error "Not a directory" will be returned if the destination is not a +keyring. Error "Permission denied" will be returned if the keyring doesn't have +write permission. Error "No such file or directory" will be returned if the key +is not linked to by the keyring. + +If the keyring is not specified, this command performs a depth-first search of +the session keyring tree and removes all the links to the nominated key that it +finds (and that it is permitted to remove). It prints the number of successful +unlinks before exiting. + +.RS +.nf +$ keyctl unlink 23 27 +.fi +.RE +.SS Move a key between keyrings. +\fBkeyctl move\fR [-f] + +This command moves a key from one keyring to another, atomically combining +"keyctl unlink " and "keyctl link ". + +If the "-f" flag is present, any matching key will be displaced from +"to_keyring"; if not present, the command will fail with the error message +"File exists" if the key would otherwise displace another key from +"to_keyring". + +.RS +.nf +$ keyctl move 23 27 29 +$ keyctl move -f 71 @u @s +.fi +.RE +.SS Search a keyring +\fBkeyctl search\fR [] + +This command non-recursively searches a keyring for a key of a particular type +and description. If found, the ID of the key will be printed on stdout and the +key will be attached to the destination keyring if present. Error "Requested +key not available" will be returned if the key is not found. + +.RS +.nf +$ keyctl search @us user debug:hello +23 +$ keyctl search @us user debug:bye +keyctl_search: Requested key not available +.fi +.RE +.SS Restrict a keyring +\fBkeyctl restrict_keyring\fR [ []] + +This command limits the linkage of keys to the given keyring using a provided +restriction scheme. The scheme is associated with a given key type, with +further details provided in the restriction option string. Options typically +contain a restriction name possibly followed by key ids or other data relevant +to the restriction. If no restriction scheme is provided, the keyring will +reject all links. + +.RS +.nf +$ keyctl restrict_keyring $1 asymmetric builtin_trusted +.RE +.SS Read a key +\fBkeyctl read\fR +.br +\fBkeyctl pipe\fR +.br +\fBkeyctl print\fR + +These commands read the payload of a key. "read" prints it on stdout as a hex +dump, "pipe" dumps the raw data to stdout and "print" dumps it to stdout +directly if it's entirely printable or as a hexdump preceded by ":hex:" if not. + +If the key type does not support reading of the payload, then error "Operation +not supported" will be returned. + +.RS +.nf +$ keyctl read 26 +1 bytes of data in key: +62 +$ keyctl print 26 +b +$ keyctl pipe 26 +$ +.fi +.RE +.SS List a keyring +\fBkeyctl list\fR +.br +\fBkeyctl rlist\fR + +These commands list the contents of a key as a keyring. "list" pretty prints +the contents and "rlist" just produces a space-separated list of key IDs. + +No attempt is made to check that the specified keyring is a keyring. + +.RS +.nf +$ keyctl list @us +2 keys in keyring: + 22: vrwsl\-\-\-\-\-\-\-\-\-\- 4043 \-1 keyring: _uid.4043 + 23: vrwsl\-\-\-\-\-\-\-\-\-\- 4043 4043 user: debug:hello +$ keyctl rlist @us +22 23 +.fi +.RE +.SS Describe a key +\fBkeyctl describe\fR +.br +\fBkeyctl rdescribe\fR [sep] + +These commands fetch a description of a keyring. "describe" pretty prints the +description in the same fashion as the "list" command; "rdescribe" prints the +raw data returned from the kernel. + +.RS +.nf +$ keyctl describe @us + \-5: vrwsl\-\-\-\-\-\-\-\-\-\- 4043 \-1 keyring: _uid_ses.4043 +$ keyctl rdescribe @us +keyring;4043;\-1;3f1f0000;_uid_ses.4043 +.fi +.RE + +The raw string is ";;;;", where \fIuid\fR +and \fIgid\fR are the decimal user and group IDs, \fIperms\fR is the +permissions mask in hex, \fItype\fR and \fIdescription\fR are the type name and +description strings (neither of which will contain semicolons). +.SS Change the access controls on a key +\fBkeyctl chown\fR +.br +\fBkeyctl chgrp\fR + +These two commands change the UID and GID associated with evaluating a key's +permissions mask. The UID also governs which quota a key is taken out of. + +The chown command is not currently supported; attempting it will earn the error +"Operation not supported" at best. + +For non-superuser users, the GID may only be set to the process's GID or a GID +in the process's groups list. The superuser may set any GID it likes. + +.RS +.nf +$ sudo keyctl chown 27 0 +keyctl_chown: Operation not supported +$ sudo keyctl chgrp 27 0 +.fi +.RE +.SS Set the permissions mask on a key +\fBkeyctl setperm\fR + +This command changes the permission control mask on a key. The mask may be +specified as a hex number if it begins "0x", an octal number if it begins "0" +or a decimal number otherwise. + +The hex numbers are a combination of: + +.RS +.nf +Possessor UID GID Other Permission Granted +======== ======== ======== ======== ================== +01000000 00010000 00000100 00000001 View +02000000 00020000 00000200 00000002 Read +04000000 00040000 00000400 00000004 Write +08000000 00080000 00000800 00000008 Search +10000000 00100000 00001000 00000010 Link +20000000 00200000 00002000 00000020 Set Attribute +3f000000 003f0000 00003f00 0000003f All +.fi +.RE + +\fIView\fR permits the type, description and other parameters of a key to be +viewed. + +\fIRead\fR permits the payload (or keyring list) to be read if supported by the +type. + +\fIWrite\fR permits the payload (or keyring list) to be modified or updated. + +\fISearch\fR on a key permits it to be found when a keyring to which it is +linked is searched. + +\fILink\fR permits a key to be linked to a keyring. + +\fISet Attribute\fR permits a key to have its owner, group membership, +permissions mask and timeout changed. + +.RS +.nf +$ keyctl setperm 27 0x1f1f1f00 +.fi +.RE +.SS Start a new session with fresh keyrings +\fBkeyctl session\fR +.br +\fBkeyctl session\fR \- [ ...] +.br +\fBkeyctl session\fR [ ...] + +These commands join or create a new keyring and then run a shell or other +program with that keyring as the session key. + +The variation with no arguments just creates an anonymous session keyring and +attaches that as the session keyring; it then exec's $SHELL. + +The variation with a dash in place of a name creates an anonymous session +keyring and attaches that as the session keyring; it then exec's the supplied +command, or $SHELL if one isn't supplied. + +The variation with a name supplied creates or joins the named keyring and +attaches that as the session keyring; it then exec's the supplied command, or +$SHELL if one isn't supplied. + +.RS +.nf +$ keyctl rdescribe @s +keyring;4043;\-1;3f1f0000;_uid_ses.4043 + +$ keyctl session +Joined session keyring: 28 + +$ keyctl rdescribe @s +keyring;4043;4043;3f1f0000;_ses.24082 + +$ keyctl session \- +Joined session keyring: 29 +$ keyctl rdescribe @s +keyring;4043;4043;3f1f0000;_ses.24139 + +$ keyctl session \- keyctl rdescribe @s +Joined session keyring: 30 +keyring;4043;4043;3f1f0000;_ses.24185 + +$ keyctl session fish +Joined session keyring: 34 +$ keyctl rdescribe @s +keyring;4043;4043;3f1f0000;fish + +$ keyctl session fish keyctl rdesc @s +Joined session keyring: 35 +keyring;4043;4043;3f1f0000;fish +.fi +.RE +.SS Instantiate a key +\fBkeyctl instantiate\fR +.br +\fBkeyctl pinstantiate\fR +.br +\fBkeyctl negate\fR +.br +\fBkeyctl reject\fR + +These commands are used to attach data to a partially set up key (as created by +the kernel and passed to +.IR /sbin/request\-key ). +"instantiate" marks a key as +being valid and attaches the data as the payload. "negate" and "reject" mark a +key as invalid and sets a timeout on it so that it'll go away after a while. +This prevents a lot of quickly sequential requests from slowing the system down +overmuch when they all fail, as all subsequent requests will then fail with +error "Requested key not found" (if negated) or the specified error (if +rejected) until the negative key has expired. + +Reject's error argument can either be a UNIX error number or one of +.BR "" "'" rejected "', '" expired "' or '" revoked "'." + +The newly instantiated key will be attached to the specified keyring. + +These commands may only be run from the program run by request\-key - a special +authorisation key is set up by the kernel and attached to the request\-key's +session keyring. This special key is revoked once the key to which it refers +has been instantiated one way or another. + +.RS +.nf +$ keyctl instantiate $1 "Debug $3" $4 +$ keyctl negate $1 30 $4 +$ keyctl reject $1 30 64 $4 +.fi +.RE + +The \fBpinstantiate\fR variant of the command reads the data from stdin rather +than taking it from the command line: + +.RS +.nf +$ echo \-n "Debug $3" | keyctl pinstantiate $1 $4 +.fi +.RE +.SS Set the expiry time on a key +\fBkeyctl timeout\fR + +This command is used to set the timeout on a key, or clear an existing timeout +if the value specified is zero. The timeout is given as a number of seconds +into the future. + +.RS +.nf +$ keyctl timeout $1 45 +.fi +.RE +.SS Retrieve a key's security context +\fBkeyctl security\fR + +This command is used to retrieve a key's LSM security context. The label is +printed on stdout. + +.RS +.nf +$ keyctl security @s +unconfined_u:unconfined_r:unconfined_t:s0\-s0:c0.c1023 +.fi +.RE +.SS Give the parent process a new session keyring +\fBkeyctl new_session\fR + +This command is used to give the invoking process (typically a shell) a new +session keyring, discarding its old session keyring. + +.RS +.nf +$ keyctl session foo +Joined session keyring: 723488146 +$ keyctl show +Session Keyring + \-3 \-\-alswrv 0 0 keyring: foo +$ keyctl new_session +490511412 +$ keyctl show +Session Keyring + \-3 \-\-alswrv 0 0 keyring: _ses +.fi +.RE + +Note that this affects the \fIparent\fP of the process that invokes the system +call, and so may only affect processes with matching credentials. +Furthermore, the change does not take effect till the parent process next +transitions from kernel space to user space - typically when the \fBwait\fP() +system call returns. +.SS Remove dead keys from the session keyring tree +\fBkeyctl reap\fR + +This command performs a depth-first search of the caller's session keyring tree +and attempts to unlink any key that it finds that is inaccessible due to +expiry, revocation, rejection or negation. It does not attempt to remove live +keys that are unavailable simply due to a lack of granted permission. + +A key that is designated reapable will only be removed from a keyring if the +caller has Write permission on that keyring, and only keyrings that grant +Search permission to the caller will be searched. + +The command prints the number of keys reaped before it exits. If the \fB\-v\fR +flag is passed then the reaped keys are listed as they're being reaped, +together with the success or failure of the unlink. +.SS Remove matching keys from the session keyring tree +\fBkeyctl\fR purge +.br +\fBkeyctl\fR purge [\-i] [\-p] +.br +\fBkeyctl\fR purge \-s + +These commands perform a depth-first search to find matching keys in the +caller's session keyring tree and attempts to unlink them. The number of +keys successfully unlinked is printed at the end. + +The keyrings must grant Read and View permission to the caller to be searched, +and the keys to be removed must also grant View permission. Keys can only be +removed from keyrings that grant Write permission. + +The first variant purges all keys of the specified type. + +The second variant purges all keys of the specified type that also match the +given description literally. The \-i flag allows a case-independent match and +the \-p flag allows a prefix match. + +The third variant purges all keys of the specified type and matching +description using the key type's comparator in the kernel to match the +description. This permits the key type to match a key with a variety of +descriptions. +.SS Get persistent keyring +\fBkeyctl\fR get_persistent [] + +This command gets the persistent keyring for either the current UID or the +specified UID and attaches it to the nominated keyring. The persistent +keyring's ID will be printed on stdout. + +The kernel will create the keyring if it doesn't exist and every time this +command is called, will reset the expiration timeout on the keyring to the +value in: +.IP +/proc/sys/kernel/keys/persistent_keyring_expiry +.P +(by default three days). Should the timeout be reached, the persistent keyring +will be removed and everything it pins can then be garbage collected. + +If a UID other than the process's real or effective UIDs is specified, then an +error will be given if the process does not have the CAP_SETUID capability. +.SS Compute a Diffie-Hellman shared secret or public key +\fBkeyctl\fR dh_compute + +This command computes either a Diffie-Hellman shared secret or the +public key corresponding to the provided private key using the +payloads of three keys. The computation is: +.IP +base ^ private (mod prime) +.P +The three inputs must be user keys with read permission. If the +provided base key contains the shared generator value, the public key +will be computed. If the provided base key contains the remote public +key value, the shared secret will be computed. + +The result is printed to stdout as a hex dump. + +.RS +.nf +$ keyctl dh_compute $1 $2 $3 +8 bytes of data in result: +00010203 04050607 +.SS Compute a Diffie-Hellman shared secret and derive key material +\fBkeyctl\fR dh_compute_kdf + +This command computes a Diffie-Hellman shared secret and derives +key material from the shared secret using a key derivation function (KDF). +The shared secret is derived as outlined above and is input to the KDF +using the specified hash type. The hash type must point to a hash name +known to the kernel crypto API. + +The operation derives key material of the length specified by the caller. + +The operation is compliant to the specification of SP800-56A. + +The result is printed to stdout as hex dump. +.SS Compute a Diffie-Hellman shared secret and apply KDF with other input +\fBkeyctl\fR dh_compute_kdf_oi + +This command is identical to the command +.IR dh_compute_kdf +to generate a Diffie-Hellman shared secret followed by a key derivation +operation. This command allows the caller to provide the other input data +(OI data) compliant to SP800-56A via stdin. +.fi +.RE +.SS Perform public-key operations with an asymmetric key +\fBkeyctl\fR pkey_query [k=v]* +.br +\fBkeyctl\fR pkey_encrypt [k=v]* > +.br +\fBkeyctl\fR pkey_decrypt [k=v]* > +.br +\fBkeyctl\fR pkey_sign [k=v]* > +.br +\fBkeyctl\fR pkey_verify [k=v]* +.PP +These commands query an asymmetric key, encrypt data with it, decrypt the +encrypted data, generate a signature over some data and verify that signature. +For encrypt, decrypt and sign, the resulting data is written to stdout; verify +reads the data and the signature files and compares them. +.PP +[\fB!\fP] NOTE that the data is of very limited capacity, with no more bits +than the size of the key. For signatures, the caller is expected to digest +the actual data and pass in the result of the digest as the datafile. The +name of the digest should be specified on the end of the command line as +"hash=". +.PP +The +.I key +ID indicates the key to use; +.I pass +is a placeholder for future password provision and should be "0" for the +moment; +.I datafile +is the unencrypted data to be encrypted, signed or to have its signature +checked; +.I encfile +is a file containing encrypted data; and +.I sigfile +is a file containing a signature. +.PP +A list of parameters in "key[=val]" form can be included on the end of the +command line. These specify things like the digest algorithm used +("hash=") or the encoding form ("enc="). +.PP +.RS +.nf +k=`keyctl padd asymmetric "" @s foo.enc +keyctl pkey_decrypt $k 0 foo.enc enc=pkcs1 >foo.hash +keyctl pkey_sign $k 0 foo.hash enc=pkcs1 hash=sha256 >foo.sig +keyctl pkey_verify $k 0 foo.hash foo.sig enc=pkcs1 hash=sha256 +.fi +.RE +.PP +See asymmetric-key(7) for more information. + +.SH ERRORS +There are a number of common errors returned by this program: + +"Not a directory" - a key wasn't a keyring. + +"Requested key not found" - the looked for key isn't available. + +"Key has been revoked" - a revoked key was accessed. + +"Key has expired" - an expired key was accessed. + +"Permission denied" - permission was denied by a UID/GID/mask combination. +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR request\-key.conf (5), +.BR keyrings (7), +.BR request\-key (8) diff --git a/man/keyctl.3 b/man/keyctl.3 new file mode 100644 index 0000000000..b0f5fdc658 --- /dev/null +++ b/man/keyctl.3 @@ -0,0 +1,123 @@ +.\" +.\" Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH KEYCTL 3 "21 Feb 2014" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_*() \- key management function wrappers +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +The +.BR keyctl () +system call is a multiplexor for a number of key management functions. These +should be called via the wrappers in the libkeyutils library. +.P +The functions can be compiled in by including the \fBkeyutils\fR header file: +.sp +.RS +.nf +.B #include +.RE +.P +and then telling the linker it should link in the library: +.sp +.RS +.nf +.B \-lkeyutils +.RE +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH KEYCTL FUNCTIONS +.BR keyctl_assume_authority (3) +.br +.BR keyctl_chown (3) +.br +.BR keyctl_capabilities (3) +.br +.BR keyctl_clear (3) +.br +.BR keyctl_describe (3) +.br +.BR keyctl_describe_alloc (3) +.br +.BR keyctl_dh_compute (3) +.br +.BR keyctl_dh_compute_alloc (3) +.br +.BR keyctl_get_keyring_ID (3) +.br +.BR keyctl_get_persistent (3) +.br +.BR keyctl_get_security (3) +.br +.BR keyctl_get_security_alloc (3) +.br +.BR keyctl_instantiate (3) +.br +.BR keyctl_instantiate_iov (3) +.br +.BR keyctl_invalidate (3) +.br +.BR keyctl_join_session_keyring (3) +.br +.BR keyctl_link (3) +.br +.BR keyctl_move (3) +.br +.BR keyctl_negate (3) +.br +.BR keyctl_pkey_dec (3) +.br +.BR keyctl_pkey_enc (3) +.br +.BR keyctl_pkey_query (3) +.br +.BR keyctl_pkey_sign (3) +.br +.BR keyctl_pkey_verify (3) +.br +.BR keyctl_read (3) +.br +.BR keyctl_read_alloc (3) +.br +.BR keyctl_reject (3) +.br +.BR keyctl_restrict_keyring (3) +.br +.BR keyctl_revoke (3) +.br +.BR keyctl_search (3) +.br +.BR keyctl_session_to_parent (3) +.br +.BR keyctl_set_reqkey_keyring (3) +.br +.BR keyctl_set_timeout (3) +.br +.BR keyctl_setperm (3) +.br +.BR keyctl_unlink (3) +.br +.BR keyctl_update (3) +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH UTILITY FUNCTIONS +.BR find_key_by_type_and_name (3) +.br +.BR recursive_key_scan (3) +.br +.BR recursive_session_key_scan (3) +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_capabilities.3 b/man/keyctl_capabilities.3 new file mode 100644 index 0000000000..cc4d86c5c6 --- /dev/null +++ b/man/keyctl_capabilities.3 @@ -0,0 +1,109 @@ +.\" +.\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_CAPABILITIES 3 "30 May 2019" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_capabilities \- Query subsystem capabilities +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_capabilities(unsigned char *" buffer ", size_t " buflen ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_capabilities () +queries the keyrings subsystem in the kernel to ask about its capabilities and +fills in the array in the buffer with bits that indicate the presence or +absence of specific features in the keyrings subsystem. +.P +The function returns the amount of data the kernel has available, irrespective +of the amount of buffer space available. If the buffer is shorter than the +data, a short copy will be made; if the buffer is larger than the data, the +excess space will be cleared. +.P +If this operation is not available in the kernel, the keyutils library will be +emulate it as best it can and the capability bit that indicates if the kernel +operation is available will be cleared. +.P +In +.IR buffer[0] , +the following capabilities exist: +.TP +.B KEYCTL_CAPS0_CAPABILITIES +This is set if the kernel supports this operation and cleared otherwise. If +it is cleared, the rest of the flags are emulated. +.TP +.B KEYCTL_CAPS0_PERSISTENT_KEYRINGS +This is set if the kernel supports persistent keyrings and cleared otherwise. +See +.BR keyctl_get_persistent ( 3 ). +.TP +.B KEYCTL_CAPS0_DIFFIE_HELLMAN +This is set if the kernel supports Diffie-Hellman calculation and cleared +otherwise. See +.BR keyctl_dh_compute ( 3 ). +.TP +.B KEYCTL_CAPS0_PUBLIC_KEY +This is set if the kernel supports public-key operations and cleared +otherwise. See +.BR keyctl_pkey_query ( 3 ). +.TP +.B KEYCTL_CAPS0_BIG_KEY +This is set if the kernel supports the big_key key type and cleared otherwise. +.TP +.B KEYCTL_CAPS0_INVALIDATE +This is set if the kernel supports key invalidation and cleared otherwise. +See +.BR keyctl_invalidate ( 3 ). +.TP +.B KEYCTL_CAPS0_RESTRICT_KEYRING +This is set if the kernel supports restrictions on keyrings and cleared +otherwise. See +.BR keyctl_restrict_keyring ( 3 ). +.TP +.B KEYCTL_CAPS0_MOVE +This is set if the kernel supports the move key operation and cleared +otherwise. See +.BR keyctl_move ( 3 ). +.P +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_capabilities () +returns the size of the data it has available, irrespective of the size of the +buffer. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B EFAULT +The buffer cannot be written to. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_chown.3 b/man/keyctl_chown.3 new file mode 100644 index 0000000000..286bdedcc4 --- /dev/null +++ b/man/keyctl_chown.3 @@ -0,0 +1,88 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_CHOWN 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_chown \- change the ownership of a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_chown(key_serial_t " key ", uid_t " uid ", gid_t " gid ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_chown () +changes the user and group ownership details of a key. +.P +A setting of +.B -1 +on either +.I uid +or +.I gid +will cause that setting to be ignored. +.P +A process that does not have the +.B SysAdmin +capability may not change a key's UID or set the key's GID to a value that +does not match the process's GID or one of its group list. +.P +The caller must have +.B setattr +permission on a key to be able change its ownership. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_chown () +returns +.B 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The specified key does not exist. +.TP +.B EKEYEXPIRED +The specified key has expired. +.TP +.B EKEYREVOKED +The specified key has been revoked. +.TP +.B EDQUOT +Changing the UID to the one specified would run that UID out of quota. +.TP +.B EACCES +The key exists, but does not grant +.B setattr +permission to the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_clear.3 b/man/keyctl_clear.3 new file mode 100644 index 0000000000..21e0c2652f --- /dev/null +++ b/man/keyctl_clear.3 @@ -0,0 +1,74 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_CLEAR 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_clear \- clear a keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_clear(key_serial_t " keyring ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_clear () +clears the contents of a +.IR keyring . +.P +The caller must have +.B write +permission on a keyring to be able clear it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_clear () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The keyring specified is invalid. +.TP +.B EKEYEXPIRED +The keyring specified has expired. +.TP +.B EKEYREVOKED +The keyring specified had been revoked. +.TP +.B EACCES +The keyring exists, but is not +.B writable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) + diff --git a/man/keyctl_describe.3 b/man/keyctl_describe.3 new file mode 100644 index 0000000000..b4f100ee8e --- /dev/null +++ b/man/keyctl_describe.3 @@ -0,0 +1,112 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_DESCRIBE 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_describe \- describe a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_describe(key_serial_t " key ", char *" buffer , +.BI "size_t" buflen ");" +.sp +.BI "long keyctl_describe_alloc(key_serial_t " key ", char **" _buffer ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_describe () +describes the attributes of a key as a NUL-terminated string. +.P +The caller must have +.B view +permission on a key to be able to get a description of it. +.P +.I buffer +and +.I buflen +specify the buffer into which the key description will be placed. If the +buffer is too small, the full size of the description will be returned, and no +copy will take place. +.P +.BR keyctl_describe_alloc () +is similar to +.BR keyctl_describe () +except that it allocates a buffer big enough to hold the description and +places the description in it. If successful, A pointer to the buffer is +placed in +.IR *_buffer . +The caller must free the buffer. +.P +The description will be a string of format: +.IP +.B "\*(lq%s;%d;%d;%08x;%s\*(rq" +.P +where the arguments are: key type name, key UID, key GID, key permissions mask +and key description. +.P +.B NOTE! +The key description will not contain any semicolons, so that should be +separated out by working backwards from the end of the string. This permits +extra information to be inserted before it by later versions of the kernel +simply by inserting more semicolon-terminated substrings. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_describe () +returns the amount of data placed into the buffer. If the buffer was too +small, then the size of buffer required will be returned, but no data will be +transferred. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.P +On success +.BR keyctl_describe_alloc () +returns the amount of data in the buffer, less the NUL terminator. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified had been revoked. +.TP +.B EACCES +The key exists, but is not +.B viewable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_dh_compute.3 b/man/keyctl_dh_compute.3 new file mode 100644 index 0000000000..5b79378d93 --- /dev/null +++ b/man/keyctl_dh_compute.3 @@ -0,0 +1,168 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Copyright (C) 2016 Intel Corporation. All rights reserved. +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_DH_COMPUTE 3 "07 Apr 2016" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_dh_compute \- Compute a Diffie-Hellman shared secret or public key +.br +keyctl_dh_compute_kdf \- Derive key from a Diffie-Hellman shared secret +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_dh_compute(key_serial_t " private ", key_serial_t " prime , +.BI "key_serial_t " base ", char *" buffer ", size_t " buflen ");" +.sp +.BI "long keyctl_dh_compute_alloc(key_serial_t " private, +.BI "key_serial_t " prime ", key_serial_t " base ", void **" _buffer ");" +.sp +.BI "long keyctl_dh_compute_kdf(key_serial_t " private ", key_serial_t " prime , +.BI "key_serial_t " base ", char *" hashname ", char *" otherinfo ", +.BI "size_t " otherinfolen ", char *" buffer ", size_t " buflen ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_dh_compute () +computes a Diffie-Hellman public key or shared secret. That computation is: +.IP +.I base +^ +.I private +( mod +.I prime +) +.P +When +.I base +is a key containing the shared generator value, the remote public key is +computed. When +.I base +is a key containing the remote public key, the shared secret is computed. +.P +.IR base ", " private ", and " prime +must all refer to +.BR user -type +keys containing the parameters for the computation. Each of these keys must +grant the caller +.B read +permission in order for them to be used. +.P +.I buffer +and +.I buflen +specify the buffer into which the computed result will be placed. +.I buflen +may be zero, in which case the buffer is not used and the minimum buffer length +is fetched. +.P +.BR keyctl_dh_compute_alloc () +is similar to +.BR keyctl_dh_compute () +except that it allocates a buffer big enough to hold the payload data and +places the data in it. If successful, a pointer to the buffer is placed in +.IR *_buffer . +The caller must free the buffer. +.P +.BR keyctl_dh_compute_kdf () +derives a key from a Diffie-Hellman shared secret according to the protocol +specified in SP800-56A. The Diffie-Hellman computation is based on the same +primitives as discussed +for +.BR keyctl_dh_compute (). +.P +To implement the protocol of SP800-56A +.I base +is a key containing the remote public key to compute the Diffie-Hellman +shared secret. That shared secret is post-processed with a key derivation +function. +.P +The +.I hashname +specifies the Linux kernel crypto API name for a hash that shall be used +for the key derivation function, such as sha256. +The +.I hashname +must be a NULL terminated string. See +.I /proc/crypto +for available hashes on the system. +.P +Following the specification of SP800-56A section 5.8.1.2 the +.I otherinfo +parameter may be provided. The format of the OtherInfo field is defined +by the caller. The caller may also specify NULL as a valid argument when +no OtherInfo data shall be processed. The length of the +.I otherinfo +parameter is specified with +.I otherinfolen +and is restricted to a maximum length by the kernel. +.P +The KDF returns the requested number of bytes specified with the +.I genlen +or the +.I buflen +parameter depending on the invoked function. +.P +.I buffer +and +.I buflen +specify the buffer into which the computed result will be placed. +.P +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_dh_compute () +returns the amount of data placed into the buffer when +.I buflen +is non-zero. When +.I buflen +is zero, the minimum buffer length to hold the data is returned. +.P +On success +.BR keyctl_dh_compute_alloc () +returns the amount of data in the buffer. +.P +On error, both functions set errno to an appropriate code and return the value +.BR -1 . +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +One of the keys specified is invalid or not readable. +.TP +.B EINVAL +The buffer pointer is invalid or buflen is too small. +.TP +.B EOPNOTSUPP +One of the keys was not a valid user key. +.TP +.B EMSGSIZE +When using +.BR keyctl_dh_compute_kdf (), +the size of either +.I otherinfolen +or +.I buflen +is too big. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.BR keyctl (1), +.br +.BR keyctl (2), +.br +.BR keyctl (3), +.br +.BR keyutils (7) diff --git a/man/keyctl_get_keyring_ID.3 b/man/keyctl_get_keyring_ID.3 new file mode 100644 index 0000000000..65252928a3 --- /dev/null +++ b/man/keyctl_get_keyring_ID.3 @@ -0,0 +1,96 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_GET_KEYRING_ID 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_get_keyring_ID \- get the ID of a special keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "key_serial_t keyctl_get_keyring_ID(key_serial_t " key "," +.BI " int " create ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_get_keyring_ID () +maps a special +.I key +or keyring ID to the serial number of the key actually representing that +feature. The serial number will be returned if that key exists. +.P +If the key or keyring does not yet exist, then if +.I create +is non-zero, the key or keyring will be created if it is appropriate to do so. +.P +The following special key IDs may be specified as +.IR key : +.TP +.B KEY_SPEC_THREAD_KEYRING +This specifies the caller's thread-specific keyring. +.TP +.B KEY_SPEC_PROCESS_KEYRING +This specifies the caller's process-specific keyring. +.TP +.B KEY_SPEC_SESSION_KEYRING +This specifies the caller's session-specific keyring. +.TP +.B KEY_SPEC_USER_KEYRING +This specifies the caller's UID-specific keyring. +.TP +.B KEY_SPEC_USER_SESSION_KEYRING +This specifies the caller's UID-session keyring. +.TP +.B KEY_SPEC_REQKEY_AUTH_KEY +This specifies the authorisation key created by +.BR request_key () +and passed to the process it spawns to generate a key. +.P +If a valid keyring ID is passed in, then this will simply be returned if the +key exists; an error will be issued if it doesn't exist. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_get_keyring_ID () +returns the serial number of the key it found. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +No matching key was found. +.TP +.B ENOMEM +Insufficient memory to create a key. +.TP +.B EDQUOT +The key quota for this user would be exceeded by creating this key or linking +it to the keyring. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_get_persistent.3 b/man/keyctl_get_persistent.3 new file mode 100644 index 0000000000..8d799576f4 --- /dev/null +++ b/man/keyctl_get_persistent.3 @@ -0,0 +1,114 @@ +.\" +.\" Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_GET_PERSISTENT 3 "20 Feb 2014" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_get_persistent \- get the persistent keyring for a user +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_get_persistent(uid_t " uid ", key_serial_t " keyring ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_get_persistent () +gets the persistent keyring for the specified user ID. Unlike the session and +user keyrings, this keyring will persist once all login sessions have been +deleted and can thus be used to carry authentication tokens for processes that +run without user interaction, such as programs started by cron. +.P +The persistent keyring will be created by the kernel if it does not yet exist. +Each time this function is called, the persistent keyring will have its +expiration timeout reset to the value in: +.IP +/proc/sys/kernel/keys/persistent_keyring_expiry +.P +(by default three days). Should the timeout be reached, the persistent keyring +will be removed and everything it pins can then be garbage collected. +.P +If +.I uid +is +.B -1 +then the calling process's real user ID will be used. If +.I uid +is not +.B -1 +then error +.B EPERM +will be given if the user ID requested does not match either the caller's real +or effective user IDs or if the calling process does not have +.B SetUid +capability. +.P +If successful, a link to the persistent keyring will be added into +.IR keyring . +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_get_persistent () +returns the serial number of the persistent keyring. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B EPERM +Not permitted to access the persistent keyring for the requested +.IR uid . +.TP +.B ENOMEM +Insufficient memory to create the persistent keyring or to extend +.IR keyring . +.TP +.B ENOKEY +.I keyring +does not exist. +.TP +.B EKEYEXPIRED +.I keyring +has expired. +.TP +.B EKEYREVOKED +.I keyring +has been revoked. +.TP +.B EDQUOT +The user does not have sufficient quota to extend +.IR keyring . +.TP +.B EACCES +.I keyring +exists, but does not grant +.B write +permission to the calling process. + +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7), +.BR persistent\-keyring (7), diff --git a/man/keyctl_get_security.3 b/man/keyctl_get_security.3 new file mode 100644 index 0000000000..a2c5b41639 --- /dev/null +++ b/man/keyctl_get_security.3 @@ -0,0 +1,102 @@ +.\" +.\" Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_GET_SECURITY 3 "26 Feb 2010" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_get_security \- retrieve a key's security context +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_get_security(key_serial_t " key ", char *" buffer , +.BI "size_t " buflen ");" +.sp +.BI "long keyctl_get_security_alloc(key_serial_t " key ", char **" _buffer ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_get_security () +retrieves the security context of a key as a NUL-terminated string. This will +be rendered in a form appropriate to the LSM in force - for instance, with +SELinux, it may look like +.IP +.B "unconfined_u:unconfined_r:unconfined_t:s0\-s0:c0.c1023" +.P +The caller must have +.B view +permission on a key to be able to get its security context. +.P +.I buffer +and +.I buflen +specify the buffer into which the string will be placed. If the buffer is too +small, the full size of the string will be returned, and no copy will take +place. +.P +.BR keyctl_get_security_alloc () +is similar to +.BR keyctl_get_security () +except that it allocates a buffer big enough to hold the string and copies the +string into it. If successful, A pointer to the buffer is placed in +.IR *_buffer . +The caller must free the buffer. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_get_security () +returns the amount of data placed into the buffer. If the buffer was too +small, then the size of buffer required will be returned, but no data will be +transferred. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.P +On success +.BR keyctl_get_security_alloc () +returns the amount of data in the buffer, less the NUL terminator. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified had been revoked. +.TP +.B EACCES +The key exists, but is not +.B viewable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_instantiate.3 b/man/keyctl_instantiate.3 new file mode 100644 index 0000000000..d436bf2195 --- /dev/null +++ b/man/keyctl_instantiate.3 @@ -0,0 +1,191 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_INSTANTIATE 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_assume_authority, keyctl_instantiate, keyctl_instantiate_iov, keyctl_reject, keyctl_negate \- key instantiation functions +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_assume_authority(key_serial_t " key ");" +.sp +.BI "long keyctl_instantiate(key_serial_t " key ", const void *" payload , +.BI "size_t " plen ", key_serial_t " keyring ");" +.sp +.BI "long keyctl_instantiate_iov(key_serial_t " key , +.BI "const struct iovec *" payload_iov ", unsigned " ioc , +.BI "key_serial_t " keyring ");" +.sp +.BI "long keyctl_negate(key_serial_t " key ", unsigned " timeout , +.BI "key_serial_t " keyring ");" +.sp +.BI "long keyctl_reject(key_serial_t " key ", unsigned " timeout , +.BI "unsigned " error ", key_serial_t " keyring ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_assume_authority () +assumes the authority for the calling thread to deal with and instantiate the +specified uninstantiated +.IR key . +.P +The calling thread must have the appropriate authorisation key resident in one +of its keyrings for this to succeed, and that authority must not have been +revoked. +.P +The authorising key is allocated by +.BR request_key() +when it needs to invoke +userspace to generate a key for the requesting process. This is then attached +to one of the keyrings of the userspace process to which the task of +instantiating the key is given: +.IP +requester -> request_key() -> instantiator +.P +Calling this function modifies the way +.BR request_key () +works when called thereafter by the calling (instantiator) thread; once the +authority is assumed, the keyrings of the initial process are added to the +search path, using the initial process's UID, GID, groups and security +context. +.P +If a thread has multiple instantiations to deal with, it may call this +function to change the authorisation key currently in effect. Supplying a +.B zero +.I key +de-assumes the currently assumed authority. +.P +.B NOTE! +This is a per-thread setting and not a per-process setting so that a +multithreaded process can be used to instantiate several keys at once. +.P +.BR keyctl_instantiate () +instantiates the payload of an uninstantiated key from the data specified. +.I payload +and +.I plen +specify the data for the new payload. +.I payload +may be NULL and +.I plen +may be zero if the key type permits that. The key type may reject the data if +it's in the wrong format or in some other way invalid. +.P +.BR keyctl_instantiate_iov () +is similar, but the data is passed in an array of iovec structs instead of in +a flat buffer. +.I payload_iov +points to the base of the array and +.I ioc +indicates how many elements there are. +.I payload_iov +may be NULL or +.I ioc +may be zero to indicate that no data is being supplied. +.P +.BR keyctl_reject () +marks a key as negatively instantiated and sets the expiration timer on it. +.I timeout +specifies the lifetime of the key in seconds. +.I error +specifies the error to be returned when a search hits the key (this is +typically +.BR EKEYREJECTED ", " EKEYREVOKED " or " EKEYEXPIRED ")." +Note that +.BR keyctl_reject () +falls back to +.BR keyctl_negate () +if the kernel does not +support it. +.P +.BR keyctl_negate () +as +.BR keyctl_reject () +with an error code of +.IB ENOKEY . +.P +Only a key for which authority has been assumed may be instantiated or +negatively instantiated, and once instantiated, the authorisation key will be +revoked and the requesting process will be able to resume. +.P +The destination +.IR keyring , +if given, is assumed to belong to the initial requester, and not the +instantiating process. Therefore, the special keyring IDs refer to the +requesting process's keyrings, not the caller's, and the requester's UID, +etc. will be used to access them. +.P +The destination keyring can be +.B zero +if no extra link is desired. +.P +The requester, not the caller, must have +.B write +permission on the destination for a link to be made there. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_instantiate () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key or keyring specified is invalid. +.TP +.B EKEYEXPIRED +The keyring specified has expired. +.TP +.B EKEYREVOKED +The key or keyring specified had been revoked, or the authorisation has been +revoked. +.TP +.B EINVAL +The payload data was invalid. +.TP +.B ENOMEM +Insufficient memory to store the new payload or to expand the destination +keyring. +.TP +.B EDQUOT +The key quota for the key's user would be exceeded by increasing the size of +the key to accommodate the new payload or the key quota for the keyring's user +would be exceeded by expanding the destination keyring. +.TP +.B EACCES +The key exists, but is not +.B writable +by the requester. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7), +.BR request\-key (8) diff --git a/man/keyctl_invalidate.3 b/man/keyctl_invalidate.3 new file mode 100644 index 0000000000..120da45053 --- /dev/null +++ b/man/keyctl_invalidate.3 @@ -0,0 +1,76 @@ +.\" +.\" Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_INVALIDATE 3 "29 Aug 2013" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_invalidate \- invalidate a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_invalidate(key_serial_t " key ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_invalidate () +invalidates a +.IR key . +The key is scheduled for immediate removal from all the keyrings that point to +it, after which it will be deleted. The key will be ignored by all searches +once this function is called even if it is not yet fully dealt with. +.P +The caller must have +.B search +permission on a key to be able to invalidate it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_invalidate () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified had been revoked. +.TP +.B EACCES +The key exists, but is not +.B searchable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_join_session_keyring.3 b/man/keyctl_join_session_keyring.3 new file mode 100644 index 0000000000..4e27717c74 --- /dev/null +++ b/man/keyctl_join_session_keyring.3 @@ -0,0 +1,84 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_JOIN_SESSION_KEYRING 3 "20 Feb 2014" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_join_session_keyring \- join a different session keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "key_serial_t keyctl_join_session_keyring(const char *" name ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_join_session_keyring () +changes the session keyring to which a process is subscribed. +.P +If +.I name +is +.B NULL +then a new anonymous keyring will be created, and the process will be +subscribed to that. +.P +If +.I name +points to a string, then if a keyring of that name is available, the process +will attempt to subscribe to that keyring, giving an error if that is not +permitted; otherwise a new keyring of that name is created and attached as the +session keyring. +.P +To attach to an extant named keyring, the keyring must have +.B search +permission available to the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_join_session_keyring () +returns the serial number of the key it found or created. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOMEM +Insufficient memory to create a key. +.TP +.B EDQUOT +The key quota for this user would be exceeded by creating this key or linking +it to the keyring. +.TP +.B EACCES +The named keyring exists, but is not +.B searchable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7), +.BR session\-keyring (7), +.BR user\-session\-keyring (7) diff --git a/man/keyctl_link.3 b/man/keyctl_link.3 new file mode 100644 index 0000000000..1185874847 --- /dev/null +++ b/man/keyctl_link.3 @@ -0,0 +1,108 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_LINK 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_link, keyctl_unlink \- link/unlink a key to/from a keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_link(key_serial_t " key ", key_serial_t " keyring ");" +.sp +.BI "long keyctl_unlink(key_serial_t " key ", key_serial_t " keyring ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_link () +creates a link from +.I keyring +to +.IR key , +displacing any link to another key of the same type and description in that +keyring if one exists. +.P +.BR keyctl_unlink () +removes the link from +.I keyring +to +.I key +if it exists. +.P +The caller must have +.B write +permission on a keyring to be able create or remove links in it. +.P +The caller must have +.B link +permission on a key to be able to create a link to it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_link () +and +.BR keyctl_unlink () +return +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key or the keyring specified are invalid. +.TP +.B EKEYEXPIRED +The key or the keyring specified have expired. +.TP +.B EKEYREVOKED +The key or the keyring specified have been revoked. +.TP +.B EACCES +The keyring exists, but is not +.B writable +by the calling process. +.P +For +.BR keyctl_link () +only: +.TP +.B ENOMEM +Insufficient memory to expand the keyring +.TP +.B EDQUOT +Expanding the keyring would exceed the keyring owner's quota. +.TP +.B EACCES +The key exists, but is not +.B linkable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) + diff --git a/man/keyctl_move.3 b/man/keyctl_move.3 new file mode 100644 index 0000000000..b241f7058f --- /dev/null +++ b/man/keyctl_move.3 @@ -0,0 +1,109 @@ +.\" +.\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_MOVE 3 "29 May 2019" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_move \- Move a key between keyrings +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_move(key_serial_t " key ", key_serial_t " from_keyring "," +.br +.BI " key_serial_t " to_keyring ", unsigned int " flags ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_move () +atomically unlinks +.I key +from +.I from_keyring +and links it into +.I to_keyring +in a single operation. Depending on the flags set, a link to any matching key +in to_keyring may get displaced. +.P +.I flags +is a bitwise-OR of zero or more of the following flags: +.P +.TP +.B KEYCTL_MOVE_EXCL +If there's a matching key in to_keyring, don't displace it but rather return +an error. +.P +The caller must have +.B write +permission on both keyring to be able create or remove links in them. +.P +The caller must have +.B link +permission on a key to be able to create a new link to it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_move () +return +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key or one of the keyrings specified are invalid. +.TP +.B ENOKEY +A key with the same type and description is present in to_keyring and +KEYCTL_MOVE_EXCL is set. +.TP +.B EKEYEXPIRED +The key or one of the keyrings specified have expired. +.TP +.B EKEYREVOKED +The key or one of the keyrings specified have been revoked. +.TP +.B EACCES +The key exists, but is not +.B linkable +by the calling process. +.TP +.B EACCES +The keyrings exist, but are not +.B writable +by the calling process. +.TP +.B ENOMEM +Insufficient memory to effect the changes. +.TP +.B EDQUOT +Expanding to_keyring would exceed the keyring owner's quota. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) + diff --git a/man/keyctl_pkey_decrypt.3 b/man/keyctl_pkey_decrypt.3 new file mode 100644 index 0000000000..47b1937f61 --- /dev/null +++ b/man/keyctl_pkey_decrypt.3 @@ -0,0 +1 @@ +.so keyctl_pkey_encrypt.3 diff --git a/man/keyctl_pkey_encrypt.3 b/man/keyctl_pkey_encrypt.3 new file mode 100644 index 0000000000..44c640e215 --- /dev/null +++ b/man/keyctl_pkey_encrypt.3 @@ -0,0 +1,113 @@ +.\" +.\" Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH KEYCTL_PKEY_ENCRYPT 3 "8 Nov 2018" Linux "Linux Public-Key Encryption" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_pkey_encrypt, keyctl_pkey_decrypt \- Encrypt and decrypt data +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_pkey_encrypt(key_serial_t " key ", const char *" info , +.BI " const void *" data ", size_t " data_len , +.BI " void *" enc ", size_t " enc_len ");" +.sp +.BI "long keyctl_pkey_decrypt(key_serial_t " key ", const char *" info , +.BI " const void *" enc ", size_t " enc_len , +.BI " void *" data ", size_t " data_len ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_pkey_encrypt () +asks the kernel to use the crypto material attached to a key to encrypt a blob +of data and +.BR keyctl_pkey_decrypt () +asks the kernel to use the key to reverse the operation and recover the +original data. Note that these operations may involve the kernel calling out +to cryptographic hardware. The caller must have +.B search +permission on a key to be able to use them in this manner. +.PP +.PP +When invoking the function, +.I key +indicates the key that will provide the cryptographic material and +.I info +points to a comma-separated string of "key[=value]" parameters that indicate +things like encoding forms and passwords to unlock the key; see +asymmetric-key(7) for more information. +.PP +.IR data " and " datalen +indicate the address and size of the decrypted data buffer and +.IR enc " and " enclen +indicate the address and size of the encrypted data buffer. The encrypt +function draws data from the decrypted data buffer and places the output into +the encryption buffer. The decrypt function does the reverse, drawing from +the encryption buffer and writing into the data buffer. +.PP +.BR keyctl_pkey_query (2) +can be called to find out how large the buffers need to be. +.PP +Note that not all asymmetric-type keys will support these operations; further, +the operations available may depend on which components of the key material are +available: typically encryption only requires the public key, but decryption +requires the private key as well. Which operations are supported on a +particular key can also be determined using the query function. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_pkey_encrypt "() and " keyctl_pkey_decrypt () +return the amount of data written into the output buffer. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified has been revoked. +.TP +.B EACCES +The key exists, but is not +.B searchable +by the calling process. +.TP +.B ENOPKG +Some facility needed to complete the requested operation is not available. +This is most probably a requested or required digest or encryption algorithm. +.TP +.B EFAULT +Bad address. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR keyctl (3), +.BR keyctl_pkey_query (3), +.BR keyctl_pkey_sign (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_pkey_query.3 b/man/keyctl_pkey_query.3 new file mode 100644 index 0000000000..dbeb0fd1ad --- /dev/null +++ b/man/keyctl_pkey_query.3 @@ -0,0 +1,137 @@ +.\" +.\" Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH KEYCTL_PKEY_QUERY 3 "8 Nov 2018" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_pkey_query \- Query public key parameters +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_pkey_query(key_serial_t " key ", const char *" info , +.BI " struct keyctl_pkey_query *" result ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_pkey_query () +queries the public key parameters associated with a kernel +key that supports these operations (typically +.BR asymmetric -type). +The caller must have +.B search +permission on the target key to be able to query its parameters. +.PP +When invoking the function, +.I key +indicates the key to be queried, +.I info +points to a comma-separated string of "key[=value]" parameters and +.I result +points to a buffer in which the result will be placed. +.PP +The parameters that can be used in the +.I info +parameter string are dependent on the type of key. Parameters can specify such +things as encoding types (such as "enc=pkcs1"); see asymmetric-key(7) for more +information. +.PP +If successful, the result is written into the following struct: +.PP +.in +4n +.EX +struct keyctl_pkey_query { + unsigned int supported_ops; + unsigned int key_size; + unsigned short max_data_size; + unsigned short max_sig_size; + unsigned short max_enc_size; + unsigned short max_dec_size; +}; +.EE +.in +.PP +The +.I supported_ops +field contains a bitmask of the following constants: +.PP +.in +4n +.TS +lB l. +KEYCTL_SUPPORTS_ENCRYPT +KEYCTL_SUPPORTS_DECRYPT +KEYCTL_SUPPORTS_SIGN +KEYCTL_SUPPORTS_VERIFY +.TE +.in +.PP +indicating what operations are supported and thus which of the other +.BR keyctl_pkey_* () +operations can be used with this key. +.PP +The +.I key_size +field indicates the number of bits in the key size and the +.IR max_data_size ", " max_sig_size ", " max_enc_size " and " max_dec_size +fields indicate the maximum sizes in bytes of a blob of data to be signed, a +signature blob, a blob to be encrypted and a blob to be decrypted respectively. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_pkey_query () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified has been revoked. +.TP +.B EACCES +The key exists, but is not +.B searchable +by the calling process. +.TP +.B ENOPKG +Some facility needed to complete the requested operation is not available. +This is most probably a requested or required digest or encryption algorithm. +.TP +.B EFAULT +Bad address. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR keyctl (3), +.BR keyctl_pkey_encrypt (3), +.BR keyctl_pkey_sign (3), +.BR asymmetric-key (7), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_pkey_sign.3 b/man/keyctl_pkey_sign.3 new file mode 100644 index 0000000000..2f17e731dc --- /dev/null +++ b/man/keyctl_pkey_sign.3 @@ -0,0 +1,133 @@ +.\" +.\" Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH KEYCTL_PKEY_SIGN 3 "8 Nov 2018" Linux "Linux Public-Key Signatures" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_pkey_sign, keyctl_pkey_verify \- Generate and verify signatures +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_pkey_sign(key_serial_t " key ", const char *" info , +.BI " const void *" data ", size_t " data_len , +.BI " void *" sig ", size_t " sig_len ");" +.sp +.BI "long keyctl_pkey_verify(key_serial_t " key ", const char *" info , +.BI " const void *" data ", size_t " data_len , +.BI " const void *" sig ", size_t " sig_len ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_pkey_sign () +asks the kernel to use the crypto data attached to a key to generate a +detached signature for a blob of data. Note that this may involve calling out +to cryptographic hardware. +.PP +.BR keyctl_pkey_verify () +asks the kernel to use the key to generate a verify the signature against the +same blob of data. This may also involve calling out to cryptographic +hardware. +.PP +The caller must have +.B search +permission on a key to be able to perform either operation. +.PP +.PP +When invoking the function, +.I key +indicates the key that will provide the cryptographic material and +.I info +points to a comma-separated string of "key[=value]" parameters that indicate +things like encoding forms and passwords to unlock the key; see +asymmetric-key(7) for more information. +.PP +.IR data " and " datalen +indicate the address and size of the buffer of data to be signed and +.IR sig " and " siglen +indicate the address and size of the signature buffer. The sign function +draws data from the data buffer, generates a signature from it and places the +output into the signature buffer. The verify function also draws data from +the data buffer, then decrypts the signature and compares the result. +.PP +Note that the data buffer is strictly limited in capacity, typically unable to +hold more bits than the size of the key. The caller is expected to have +pre-digested the actual data and will thus pass the digest output to this +function. The name of the digest used should be passed as part of the info +string as \fPhash=\fR for use in constructing the signature metadata. +.PP +.BR keyctl_pkey_query (2) +can be called to find out how large the buffers need to be and what the +maximum size of the data can be for a specific signature encoding. +.PP +Note that not all asymmetric-type keys will support these operations; further, +the operations available may depend on which components of the key material are +available: typically encryption only requires the public key, but decryption +requires the private key as well. Which operations are supported on a +particular key can also be determined using the query function. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_pkey_sign () +returns the amount of data written into the signature buffer. +.BR keyctl_pkey_verify () +will return 0 in this case as it doesn't write to userspace. +.PP +On error the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified has been revoked. +.TP +.B EACCES +The key exists, but is not +.B searchable +by the calling process. +.TP +.BR EINVAL ", " EBADMSG ", " EOVERFLOW +Some part of the key material or signature data is bad. +.TP +.BR EKEYREJECTED +Signature verification failed. +.TP +.B ENOPKG +Some facility needed to complete the requested operation is not available. +This is most probably a requested or required digest or encryption algorithm. +.TP +.B EFAULT +Bad address. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR keyctl (3), +.BR keyctl_pkey_query (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_pkey_verify.3 b/man/keyctl_pkey_verify.3 new file mode 100644 index 0000000000..05351137df --- /dev/null +++ b/man/keyctl_pkey_verify.3 @@ -0,0 +1 @@ +.so keyctl_pkey_sign.3 diff --git a/man/keyctl_read.3 b/man/keyctl_read.3 new file mode 100644 index 0000000000..852bc055c2 --- /dev/null +++ b/man/keyctl_read.3 @@ -0,0 +1,112 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_READ 3 "21 Feb 2014" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_read \- read a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_read(key_serial_t " key ", char *" buffer , +.BI "size_t" buflen ");" +.sp +.BI "long keyctl_read_alloc(key_serial_t " key ", void **" _buffer ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_read () +reads the payload of a key if the key type supports it. +.P +The caller must have +.B read +permission on a key to be able to read it. +.P +.I buffer +and +.I buflen +specify the buffer into which the payload data will be placed. If the buffer +is too small, then the full size of the payload will be returned, and the +contents of the buffer may be overwritten in some undefined way. +.P +.BR keyctl_read_alloc () +is similar to +.BR keyctl_read () +except that it allocates a buffer big enough to hold the payload data and +places the data in it. If successful, a pointer to the buffer is placed in +.IR *_buffer . +The caller must free the buffer. +.P +.BR keyctl_read_alloc () +adds a NUL character after the data it retrieves, though this is not counted +in the size value it returns. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH READING KEYRINGS +This call can be used to list the contents of a keyring. The data is +presented to the user as an array of +.B key_serial_t +values, each of which corresponds to a key to which the keyring holds a link. +.P +The size of the keyring will be sizeof(key_serial_t) multiplied by the number +of keys. The size of key_serial_t is invariant across different word sizes, +though the byte-ordering is as appropriate for the kernel. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_read () +returns the amount of data placed into the buffer. If the buffer was too +small, then the size of buffer required will be returned, and the contents of +the buffer may have been overwritten in some undefined way. +.P +On success +.BR keyctl_read_alloc () +returns the amount of data in the buffer. +.P +On error, both functions set +.I errno +to an appropriate code and return the value +.BR -1 . +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified had been revoked. +.TP +.B EACCES +The key exists, but is not +.B readable +by the calling process. +.TP +.B EOPNOTSUPP +The key type does not support reading of the payload data. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_restrict_keyring.3 b/man/keyctl_restrict_keyring.3 new file mode 100644 index 0000000000..468d5b45f0 --- /dev/null +++ b/man/keyctl_restrict_keyring.3 @@ -0,0 +1,82 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Copyright (C) 2017 Intel Corporation. All rights reserved. +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_RESTRICT_KEYRING 3 "28 Feb 2017" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_restrict_keyring \- restrict keys that may be linked to a keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_restrict_keyring(key_serial_t " keyring , +.BI "const char *" type ", const char *" restriction ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_restrict_keyring () +limits the linkage of keys to the given +.I keyring +using a provided key +.I type +and +.I restriction +scheme. The available options vary depending on the key type, and +typically contain a restriction name possibly followed by key ids or +other data relevant to the restriction. If the type and restriction are +both +.B NULL, +the keyring will reject all links. +.P +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_restrict_keyring () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B EDEADLK +A restriction cycle was avoided. Two keyrings cannot restrict each other. +.TP +.B EEXIST +The keyring is already restricted. +.TP +.B EINVAL +The restriction string is invalid or too large. +.TP +.B ENOKEY +The key type in the restriction is invalid or not available. +.TP +.B ENOTDIR +The provided key id references an item that is not a keyring. +.TP +.B ENOENT +The key type exists but does not support restrictions. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR keyctl (2), +.BR keyctl (3), +.BR keyutils (7) diff --git a/man/keyctl_revoke.3 b/man/keyctl_revoke.3 new file mode 100644 index 0000000000..914a253182 --- /dev/null +++ b/man/keyctl_revoke.3 @@ -0,0 +1,73 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_REVOKE 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_revoke \- revoke a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_revoke(key_serial_t " key ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_revoke () +marks a key as being revoked. +.P +After this operation has been performed on a key, attempts to access it will +meet with error +.BR EKEYREVOKED . +.P +The caller must have +.B write +permission on a key to be able revoke it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_revoke () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The specified key does not exist. +.TP +.B EKEYREVOKED +The key has already been revoked. +.TP +.B EACCES +The named key exists, but is not +.B writable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_search.3 b/man/keyctl_search.3 new file mode 100644 index 0000000000..f3e7bc5182 --- /dev/null +++ b/man/keyctl_search.3 @@ -0,0 +1,138 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_SEARCH 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_search \- search a keyring for a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_search(key_serial_t " keyring ", const char *" type , +.BI "const char *" description ", key_serial_t " destination ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_search () +recursively searches the +.I keyring +for a key of the specified +.I type +and +.IR description . +.P +If found, the key will be attached to the +.I destination +keyring (if given), and its serial number will be returned. +.P +The source keyring must grant +.B search +permission to the caller, and for a key to be found, it must also grant +.B search +permission to the caller. Child keyrings will be only be recursively searched +if they grant +.B search +permission to the caller as well. +.P +If the destination keyring is +.BR zero , +no attempt will be made to forge a link to the key, and just the serial number +will be returned. +.P +If the destination keyring is given, then the link may only be formed if the +found key grants the caller +.B link +permission and the destination keyring grants the caller +.B write +permission. +.P +If the search is successful, and if the destination keyring already contains a +link to a key that matches the specified +.IR type " and " description , +then that link will be replaced by a link to the found key. +.P +The source keyring and destination keyring serial numbers may be those of +valid keyrings to which the caller has appropriate permission, or they may be +special keyring IDs: +.TP +.B KEY_SPEC_THREAD_KEYRING +This specifies the caller's thread-specific keyring. +.TP +.B KEY_SPEC_PROCESS_KEYRING +This specifies the caller's process-specific keyring. +.TP +.B KEY_SPEC_SESSION_KEYRING +This specifies the caller's session-specific keyring. +.TP +.B KEY_SPEC_USER_KEYRING +This specifies the caller's UID-specific keyring. +.TP +.B KEY_SPEC_USER_SESSION_KEYRING +This specifies the caller's UID-session keyring. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_search () +returns the serial number of the key it found. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +One of the keyrings doesn't exist, no key was found by the search, or the only +key found by the search was a negative key. +.TP +.B ENOTDIR +One of the keyrings is a valid key that isn't a keyring. +.TP +.B EKEYEXPIRED +One of the keyrings has expired, or the only key found was expired. +.TP +.B EKEYREVOKED +One of the keyrings has been revoked, or the only key found was revoked. +.TP +.B ENOMEM +Insufficient memory to expand the destination keyring. +.TP +.B EDQUOT +The key quota for this user would be exceeded by creating a link to the found +key in the destination keyring. +.TP +.B EACCES +The source keyring didn't grant +.B search +permission, the destination keyring didn't grant +.B write +permission or the found key didn't grant +.B link +permission to the caller. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +Although this is a Linux system call, it is not present in +.I libc +but can be found rather in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_session_to_parent.3 b/man/keyctl_session_to_parent.3 new file mode 100644 index 0000000000..829b3be9c3 --- /dev/null +++ b/man/keyctl_session_to_parent.3 @@ -0,0 +1,77 @@ +.\" +.\" Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_SESSION_TO_PARENT 3 "20 Feb 2014" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_session_to_parent \- set the parent process's session keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_session_to_parent();" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_session_to_parent () +changes the session keyring to which the calling process's parent subscribes +to be the that of the calling process. +.P +The keyring must have +.B link +permission available to the calling process, the parent process must have the +same UIDs/GIDs as the calling process, and the LSM must not reject the +replacement. Furthermore, this may not be used to affect init or a kernel +thread. +.P +Note that the replacement will not take immediate effect upon the parent +process, but will rather be deferred to the next time it returns to userspace +from kernel space. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_session_to_parent () +returns 0. On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOMEM +Insufficient memory to create a key. +.TP +.B EPERM +The credentials of the parent don't match those of the caller. +.TP +.B EACCES +The named keyring exists, but is not +.B linkable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7), +.BR session\-keyring (7), +.BR user\-session-keyring (7) diff --git a/man/keyctl_set_reqkey_keyring.3 b/man/keyctl_set_reqkey_keyring.3 new file mode 100644 index 0000000000..00da58680d --- /dev/null +++ b/man/keyctl_set_reqkey_keyring.3 @@ -0,0 +1,101 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_SET_REQKEY_KEYRING 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_set_reqkey_keyring \- set the implicit destination keyring +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_set_reqkey_keyring(int " reqkey_defl ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_set_reqkey_keyring () +sets the default destination for implicit key requests for the current thread +and returns the old setting. +.P +After this operation has been issued, keys acquired by implicit key requests, +such as might be performed by +.BR open () +on an AFS or NFS filesystem, will be +linked by default to the specified keyring by this function. +.P +The valid values of +.I reqkey_defl +are: +.TP +.B KEY_REQKEY_DEFL_NO_CHANGE +This makes no change to the current setting. +.TP +.B KEY_REQKEY_DEFL_THREAD_KEYRING +This makes the thread-specific keyring the default destination. +.TP +.B KEY_REQKEY_DEFL_PROCESS_KEYRING +This makes the process-specific keyring the default destination. +.TP +.B KEY_REQKEY_DEFL_SESSION_KEYRING +This makes the session keyring the default destination. +.TP +.B KEY_REQKEY_DEFL_USER_KEYRING +This makes the UID-specific keyring the default destination. +.TP +.B KEY_REQKEY_DEFL_USER_SESSION_KEYRING +This makes the UID-specific session keyring the default destination. +.TP +.B KEY_REQKEY_DEFL_DEFAULT +This selects the default behaviour which is to use the thread-specific keyring +if there is one, otherwise the process-specific keyring if there is one, +otherwise the session keyring if there is one, otherwise the UID-specific +session keyring. +.P +This setting is inherited across +.BR fork () +and +.BR exec (). + +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_set_reqkey_keyring () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B EINVAL +The value of +.I reqkey_defl +is invalid. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyutils (7), +.BR keyrings (7), +.BR request\-key (8) diff --git a/man/keyctl_set_timeout.3 b/man/keyctl_set_timeout.3 new file mode 100644 index 0000000000..1b7ec949c0 --- /dev/null +++ b/man/keyctl_set_timeout.3 @@ -0,0 +1,81 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_SET_TIMEOUT 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_set_timeout \- set the expiration timer on a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_set_timeout(key_serial_t " key ", unsigned " timeout ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_set_timeout () +sets the expiration timer on a key to +.I timeout +seconds into the future. Setting +.I timeout +to +.B zero +cancels the expiration, assuming the key hasn't already expired. +.P +When the key expires, further attempts to access it will be met with error +.BR EKEYEXPIRED . +.P +The caller must have +.B setattr +permission on a key to be able change its permissions mask. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_set_timeout () +returns +.B 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The specified key does not exist. +.TP +.B EKEYEXPIRED +The specified key has already expired. +.TP +.B EKEYREVOKED +The specified key has been revoked. +.TP +.B EACCES +The named key exists, but does not grant +.B setattr +permission to the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_setperm.3 b/man/keyctl_setperm.3 new file mode 100644 index 0000000000..0a4426d337 --- /dev/null +++ b/man/keyctl_setperm.3 @@ -0,0 +1,130 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_SETPERM 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_setperm \- change the permissions mask on a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_setperm(key_serial_t " key ", key_perm_t " perm ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_setperm () +changes the permissions mask on a key. +.P +A process that does not have the +.B SysAdmin +capability may not change the permissions mask on a key that doesn't have the +same UID as the caller. +.P +The caller must have +.B setattr +permission on a key to be able change its permissions mask. +.P +The permissions mask is a bitwise-OR of the following flags: +.TP +.B KEY_xxx_VIEW +Grant permission to view the attributes of a key. +.TP +.B KEY_xxx_READ +Grant permission to read the payload of a key or to list a keyring. +.TP +.B KEY_xxx_WRITE +Grant permission to modify the payload of a key or to add or remove links +to/from a keyring. +.TP +.B KEY_xxx_SEARCH +Grant permission to find a key or to search a keyring. +.TP +.B KEY_xxx_LINK +Grant permission to make links to a key. +.TP +.B KEY_xxx_SETATTR +Grant permission to change the ownership and permissions attributes of a key. +.TP +.B KEY_xxx_ALL +Grant all the above. +.P +The +.RB ' xxx ' +in the above should be replaced by one of: +.TP +.B POS +Grant the permission to a process that possesses the key (has it attached +searchably to one of the process's keyrings). +.TP +.B USR +Grant the permission to a process with the same UID as the key. +.TP +.B GRP +Grant the permission to a process with the same GID as the key, or with a +match for the key's GID amongst that process's Groups list. +.TP +.B OTH +Grant the permission to any other process. +.P +Examples include: +.BR KEY_POS_VIEW ", " KEY_USR_READ ", " KEY_GRP_SEARCH " and " KEY_OTH_ALL . +.P +User, group and other grants are exclusive: if a process qualifies in +the 'user' category, it will not qualify in the 'groups' category; and if a +process qualifies in either 'user' or 'groups' then it will not qualify in +the 'other' category. +.P +Possessor grants are cumulative with the grants from the 'user', 'groups' +and 'other' categories. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_setperm () +returns +.B 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The specified key does not exist. +.TP +.B EKEYEXPIRED +The specified key has expired. +.TP +.B EKEYREVOKED +The specified key has been revoked. +.TP +.B EACCES +The named key exists, but does not grant +.B setattr +permission to the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyctl_update.3 b/man/keyctl_update.3 new file mode 100644 index 0000000000..17fbdb4635 --- /dev/null +++ b/man/keyctl_update.3 @@ -0,0 +1,96 @@ +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH KEYCTL_UPDATE 3 "4 May 2006" Linux "Linux Key Management Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyctl_update \- update a key +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "long keyctl_update(key_serial_t " key ", const void *" payload , +.BI "size_t " plen ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR keyctl_update () +updates the payload of a key if the key type permits it. +.P +The caller must have +.B write +permission on a key to be able update it. +.P +.I payload +and +.I plen +specify the data for the new payload. +.I payload +may be NULL and +.I plen +may be zero if the key type permits that. The key type may reject the data if +it's in the wrong format or in some other way invalid. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +On success +.BR keyctl_update () +returns +.BR 0 . +On error, the value +.B -1 +will be returned and +.I errno +will have been set to an appropriate error. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +The key specified is invalid. +.TP +.B EKEYEXPIRED +The key specified has expired. +.TP +.B EKEYREVOKED +The key specified had been revoked. +.TP +.B EINVAL +The payload data was invalid. +.TP +.B ENOMEM +Insufficient memory to store the new payload. +.TP +.B EDQUOT +The key quota for this user would be exceeded by increasing the size of the +key to accommodate the new payload. +.TP +.B EACCES +The key exists, but is not +.B writable +by the calling process. +.TP +.B EOPNOTSUPP +The key type does not support the update operation on its keys. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +This is a library function that can be found in +.IR libkeyutils . +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR add_key (2), +.BR keyctl (2), +.BR request_key (2), +.BR keyctl (3), +.BR keyrings (7), +.BR keyutils (7) diff --git a/man/keyutils.7 b/man/keyutils.7 new file mode 100644 index 0000000000..e17253b900 --- /dev/null +++ b/man/keyutils.7 @@ -0,0 +1,105 @@ +.\" +.\" Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH KEYUTILS 7 "21 Feb 2014" Linux "Kernel key management" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +keyutils \- in-kernel key management utilities +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +The +.B keyutils +package is a library and a set of utilities for accessing the kernel +\fBkeyrings\fP facility. +.P +A header file is supplied to provide the definitions and declarations required +to access the library: +.P +.RS +.B #include +.RE +.P +To link with the library, the following: +.P +.RS +.B \-lkeyutils +.RE +.P +should be specified to the linker. +.P +Three system calls are provided: +.TP +.BR add_key (2) +Supply a new key to the kernel. +.TP +.BR request_key (2) +Find an existing key for use, or, optionally, create one if one does not exist. +.TP +.BR keyctl (2) +Control a key in various ways. The library provides a variety of wrappers +around this system call and those should be used rather than calling it +directly. +.P +See the +.BR add_key (2), +.BR request_key (2), +and +.BR keyctl (2) +manual pages for more information. +.P +The \fBkeyctl\fP() wrappers are listed on the +.BR keyctl (3) +manual page. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH UTILITIES +.P +A program is provided to interact with the kernel facility by a number of +subcommands, e.g.: +.P +.RS +.B keyctl add user foo bar @s +.RE +.P +See the +.BR keyctl (1) +manual page for information on that. +.P +The kernel has the ability to upcall to userspace to fabricate new keys. This +can be triggered by \fBrequest_key\fP(), but userspace is better off using +\fBadd_key\fP() instead if it possibly can. +.P +The upcalling mechanism is usually routed via the +.BR request\-key (8) +program. What this does with any particular key is configurable in: +.P +.RS +.I /etc/request\-key.conf +.br +.I /etc/request\-key.d/ +.RE +.P +See the +.BR request\-key.conf (5) +and the +.BR request\-key (8) +manual pages for more information. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR keyctl (3), +.BR keyrings (7), +.BR persistent\-keyring (7), +.BR process\-keyring (7), +.BR session\-keyring (7), +.BR thread\-keyring (7), +.BR user\-keyring (7), +.BR user\-session\-keyring (7), +.BR pam_keyinit (8) diff --git a/man/recursive_key_scan.3 b/man/recursive_key_scan.3 new file mode 100644 index 0000000000..86580022af --- /dev/null +++ b/man/recursive_key_scan.3 @@ -0,0 +1,90 @@ +.\" +.\" Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH RECURSIVE_KEY_SCAN 3 "10 Mar 2011" Linux "Linux Key Utility Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +recursive_key_scan, recursive_session_key_scan \- apply a function to all keys in a keyring tree +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "typedef int (*" recursive_key_scanner_t ")(key_serial_t " parent , +.BI " key_serial_t " key ", char *" desc ", int " desc_len ", void *" data ");" +.sp +.BI "long recursive_key_scan(key_serial_t " keyring , +.BI " recursive_key_scanner_t " func ", void *" data ");" +.br +.BI "long recursive_session_key_scan(recursive_key_scanner_t " func , +.BI " void *" data ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR recursive_key_scan () +performs a depth-first recursive scan of the specified +.I keyring +tree and applies +.I func +to every link found in the accessible keyrings in that tree. +.I data +is passed to each invocation of func. +.P +The return values of +.I func +are summed and returned as the overall return value. Errors are ignored. +Inaccessible keyrings are not scanned, but links to them are still passed to +func. +.P +.BR recursive_session_key_scan () +works exactly like +.BR recursive_key_scan () +with the caller's session keyring specified as the starting keyring. +.P +The callback function is called for each link found in all the keyrings in the +nominated tree and so may be called multiple times for a particular key if that +key has multiple links to it. +.P +The callback function is passed the following parameters: +.TP +.B parent +The keyring containing the link or 0 for the initial key. +.TP +.BR key +The key to which the link points. +.TP +.BR desc " and " desc_len +A pointer to the raw description and its length as retrieved with +.BR keyctl_describe_alloc (). +These will be NULL and \-1 respectively if the description couldn't be +retrieved and +.I errno +will retain the error from +.BR keyctl_describe_alloc (). +.TP +.B data +The data passed to the scanner function. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +These functions return the sum of the results of the callback functions they +invoke. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +Ignored. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +When linking, +.B \-lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.ad l +.nh +.BR keyctl (3), +.BR keyctl_describe_alloc (3), +.BR keyrings (7) diff --git a/man/request-key.8 b/man/request-key.8 new file mode 100644 index 0000000000..50a750641e --- /dev/null +++ b/man/request-key.8 @@ -0,0 +1,61 @@ +.\" +.\" Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH REQUEST-KEY 8 "15 Nov 2011" Linux "Linux Key Management Utilities" +.SH NAME +request\-key \- handle key instantiation callback requests from the kernel +.SH SYNOPSIS +\fB/sbin/request\-key \fR + [] +.SH DESCRIPTION +This program is invoked by the kernel when the kernel is asked for a key that +it doesn't have immediately available. The kernel creates a partially set up +key and then calls out to this program to instantiate it. It is not intended +to be called directly. +.PP +However, for debugging purposes, it can be given some options on the command +line: +.IP \fB-d\fP +Turn on debugging mode. In this mode, no attempts are made to access any keys +and, if a handler program is selected, it won't be executed; instead, this +program will print a message and exit 0. +.IP \fB-D \fP +In debugging mode, use the proposed key description specified with this rather +than the sample ("user;0;0;1f0000;debug:1234") built into the program. +.IP \fB-l\fP +Use configuration from the current directory. The program will use +.IR request-key.d/* " and " request-key.conf +from the current directory rather than from +.IR /etc . +.IP \fB-n\fP +Don't log to the system log. Ordinarily, error messages and debugging messages +will be copied to the system log - this will prevent that. +.IP \fB-v\fP +Turn on debugging output. This may be specified multiple times to produce +increasing levels of verbosity. +.IP \fB--version\fP +Print the program version and exit. +.SH ERRORS +All errors will be logged to the syslog. +.SH FILES +.ul +/etc/request\-key.d/*.conf +.ul 0 +Individual configuration files. +.P +.ul +/etc/request\-key.conf +.ul 0 +Fallback configuration file. +.SH SEE ALSO +.ad l +.nh +.BR keyctl (1), +.BR request\-key.conf (5), +.BR keyrings (7) diff --git a/man/request-key.conf.5 b/man/request-key.conf.5 new file mode 100644 index 0000000000..276c7718c4 --- /dev/null +++ b/man/request-key.conf.5 @@ -0,0 +1,145 @@ +.\" -*- nroff -*- +.\" Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. +.\" Written by David Howells (dhowells@redhat.com) +.\" +.\" This program is free software; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License +.\" as published by the Free Software Foundation; either version +.\" 2 of the License, or (at your option) any later version. +.\" +.TH REQUEST-KEY.CONF 5 "15 November 2011" Linux "Linux Key Management Utilities" +.SH NAME +request\-key.conf \- Instantiation handler configuration file +.SH DESCRIPTION +.P +These files are used by the /sbin/request\-key program to determine which +program it should run to instantiate a key. +.P +request\-key looks for the best match, reading all the following files: +.IP + /etc/request\-key.d/*.conf +.br + /etc/request\-key.conf +.P +If it doesn't find a match, it will return an error +and the kernel will automatically negate the key. +.P +The best match is defined as the line with the shortest wildcard skips, ranking +the columns in order left to right. If two lines have the same length skips, +then the first read is the one taken. +.P +In the files, any blank line or line beginning with a hash mark '#' is +considered to be a comment and ignored. +.P +All other lines are assumed to be command lines with a number of white space +separated fields: +.P + ... +.P +The first four fields are used to match the parameters passed to request\-key by +the kernel. \fIop\fR is the operation type; currently the only supported +operation is "create". +.P +\fItype\fR, \fIdescription\fR and \fIcallout\-info\fR match the three +parameters passed to \fBkeyctl request2\fR or the \fBrequest_key()\fR system +call. Each of these may contain one asterisk '*' character as a wildcard +anywhere within the string. +.P +Should a match be made, the program specified by will be exec'd. This +must have a fully qualified path name. argv[0] will be set from the part of the +program name that follows the last slash '/' character. +.P +If the program name is prefixed with a pipe bar character '|', then the program +will be forked and exec'd attached to three pipes. The callout information will +be piped to it on it's stdin and the intended payload data will be retrieved +from its stdout. Anything sent to stderr will be posted in syslog. If the +program exits 0, then /sbin/request\-key will attempt to instantiate the key +with the data read from stdout. If it fails in any other way, then request\-key +will attempt to execute the appropriate 'negate' operation command. +.P +The program arguments can be substituted with various macros. Only complete +argument substitution is supported - macro substitutions can't be embedded. All +macros begin with a percent character '%'. An argument beginning with two +percent characters will have one of them discarded. +.P +The following macros are supported: +.P +.RS +%o Operation type +.br +%k Key ID +.br +%t Key type +.br +%d Key description +.br +%c Callout information +.br +%u Key UID +.br +%g Key GID +.br +%T Requestor's thread keyring +.br +%P Requestor's process keyring +.br +%S Requestor's session keyring +.RE +.P +There's another macro substitution too that permits the interpolation of the +contents of a key: +.P +.RS +%{:} +.RE +.P +This performs a lookup for a key of the given type and description on the +requestor's keyrings, and if found, substitutes the contents for the macro. If +not found an error will be logged and the key under construction will be +negated. +.SH EXAMPLE +.P +A basic file will be installed in the /etc. This will contain two debugging +lines that can be used to test the installation: +.P +.RS +create user debug:* negate /bin/keyctl negate %k 30 %S +.br +create user debug:loop:* * |/bin/cat +.br +create user debug:* * /usr/share/keyutils/request\-key\-debug.sh %k %d %c %S +.br +negate * * * /bin/keyctl negate %k 30 %S +.RE +.P +This is set up so that something like: +.P +.RS +keyctl request2 user debug:xxxx negate +.RE +.P +will create a negative user-defined key, something like: +.P +.RS +keyctl request2 user debug:yyyy spoon +.RE +.P +will create an instantiated user-defined key with "Debug spoon" as the payload, +and something like: +.P +.RS +keyctl request2 user debug:loop:zzzz abcdefghijkl +.RE +.P +will create an instantiated user-defined key with the callout information as +the payload. +.SH FILES +.ul +/etc/request\-key.conf +.ul 0 +.br +.ul +/etc/request\-key.d/*.conf +.ul 0 +.SH SEE ALSO +\fBkeyctl\fR(1), \fBrequest\-key.conf\fR(5) diff --git a/request-key-debug.sh b/request-key-debug.sh new file mode 100755 index 0000000000..83af01d704 --- /dev/null +++ b/request-key-debug.sh @@ -0,0 +1,33 @@ +#!/bin/sh +############################################################################### +# +# Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# +############################################################################### +# +# Request key debugging +# +# Call: request-key-debug.sh +# + +echo RQDebug keyid: $1 +echo RQDebug desc: $2 +echo RQDebug callout: $3 +echo RQDebug session keyring: $4 + +if [ "$3" != "neg" ] +then + keyctl instantiate $1 "Debug $3" $4 || exit 1 +else + cat /proc/keys + echo keyctl negate $1 30 $4 + keyctl negate $1 30 $4 +fi + +exit 0 diff --git a/request-key.c b/request-key.c new file mode 100644 index 0000000000..bf47c0a484 --- /dev/null +++ b/request-key.c @@ -0,0 +1,955 @@ +/* request-key.c: hand a key request off to the appropriate process + * + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * /sbin/request-key [] + * + * Searches the specified session ring for a key indicating the command to run: + * type: "user" + * desc: "request-key:" + * data: command name, e.g.: "/home/dhowells/request-key-create.sh" + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "keyutils.h" + + +struct parameters { + key_serial_t key_id; + char *op; + char *key_type; + char *key_desc; + char *callout_info; + char *key; + char *uid; + char *gid; + char *thread_keyring; + char *process_keyring; + char *session_keyring; + int len; + int oplen; + int ktlen; + int kdlen; + int cilen; + +}; + +static int verbosity; +static int xlocaldirs; +static int xnolog; +static int debug_mode; +static char conffile[PATH_MAX + 1]; +static int confline; +static int norecurse; + +static char cmd[4096 + 2], cmd_conffile[PATH_MAX + 1]; +static unsigned int cmd_wildness[4] = { UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX }; +static int cmd_len, cmd_confline; + +static void lookup_action(struct parameters *params) + __attribute__((noreturn)); +static void scan_conf_dir(struct parameters *params, const char *confdir); +static void scan_conf_file(struct parameters *params, int dirfd, const char *conffile); + +static void execute_program(struct parameters *params, + char *cmdline) + __attribute__((noreturn)); + +static void pipe_to_program(struct parameters *params, + char *prog, + char **argv) + __attribute__((noreturn)); + +static int match(const char *pattern, int plen, const char *datum, int dlen, + unsigned int *wildness); + +static void debug(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +static void debug(const char *fmt, ...) +{ + va_list va; + + if (verbosity) { + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + + if (!xnolog) { + openlog("request-key", 0, LOG_AUTHPRIV); + + va_start(va, fmt); + vsyslog(LOG_DEBUG, fmt, va); + va_end(va); + + closelog(); + } + } +} + +static void error(const char *fmt, ...) __attribute__((noreturn, format(printf, 1, 2))); +static void error(const char *fmt, ...) +{ + va_list va; + + if (verbosity) { + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + } + + if (!xnolog) { + openlog("request-key", 0, LOG_AUTHPRIV); + + va_start(va, fmt); + vsyslog(LOG_ERR, fmt, va); + va_end(va); + + closelog(); + } + + exit(1); +} + +#define file_error(FMT, ...) error("%s: "FMT, conffile, ## __VA_ARGS__) +#define line_error(FMT, ...) error("%s:%d: "FMT, conffile, confline, ## __VA_ARGS__) + +static void oops(int x) +{ + error("Died on signal %d", x); +} + +/*****************************************************************************/ +/* + * + */ +int main(int argc, char *argv[]) +{ + struct parameters params; + char *test_desc = "user;0;0;1f0000;debug:1234"; + char *buf; + int ret, ntype, dpos, n, fd, opt; + + if (argc == 2 && strcmp(argv[1], "--version") == 0) { + printf("request-key from %s (Built %s)\n", + keyutils_version_string, keyutils_build_string); + return 0; + } + + signal(SIGSEGV, oops); + signal(SIGBUS, oops); + signal(SIGPIPE, SIG_IGN); + + while (opt = getopt(argc, argv, "D:dlnv"), + opt != -1) { + switch (opt) { + case 'D': + test_desc = optarg; + break; + case 'd': + debug_mode = 1; + break; + case 'l': + xlocaldirs = 1; + break; + case 'n': + xnolog = 1; + break; + case 'v': + verbosity++; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc != 7 && argc != 8) + error("Unexpected argument count: %d\n", argc); + + fd = open("/dev/null", O_RDWR); + if (fd < 0) + error("open"); + if (fd > 2) { + close(fd); + } + else if (fd < 2) { + ret = dup(fd); + if (ret < 0) + error("dup failed: %m\n"); + + if (ret < 2 && dup(fd) < 0) + error("dup failed: %m\n"); + } + + params.op = argv[0]; + params.key = argv[1]; + params.uid = argv[2]; + params.gid = argv[3]; + params.thread_keyring = argv[4]; + params.process_keyring = argv[5]; + params.session_keyring = argv[6]; + params.callout_info = argv[7]; + + params.key_id = atoi(params.key); + + /* assume authority over the key + * - older kernel doesn't support this function + */ + if (!debug_mode) { + ret = keyctl_assume_authority(params.key_id); + if (ret < 0 && !(argc == 8 || errno == EOPNOTSUPP)) + error("Failed to assume authority over key %d (%m)\n", + params.key_id); + } + + /* ask the kernel to describe the key to us */ + if (!debug_mode) { + ret = keyctl_describe_alloc(params.key_id, &buf); + if (ret < 0) + goto inaccessible; + } else { + buf = strdup(test_desc); + } + + /* extract the type and description from the key */ + debug("Key descriptor: \"%s\"\n", buf); + ntype = -1; + dpos = -1; + + n = sscanf(buf, "%*[^;]%n;%*d;%*d;%x;%n", &ntype, &n, &dpos); + if (n != 1) + error("Failed to parse key description\n"); + + params.key_type = buf; + params.key_type[ntype] = 0; + params.key_desc = buf + dpos; + + debug("Key type: %s\n", params.key_type); + debug("Key desc: %s\n", params.key_desc); + + /* get hold of the callout info */ + if (!params.callout_info) { + void *tmp; + + if (keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, &tmp) < 0) + error("Failed to retrieve callout info (%m)\n"); + + params.callout_info = tmp; + } + + debug("CALLOUT: '%s'\n", params.callout_info); + + /* determine the action to perform */ + params.oplen = strlen(params.op); + params.ktlen = strlen(params.key_type); + params.kdlen = strlen(params.key_desc); + params.cilen = strlen(params.callout_info); + lookup_action(¶ms); + +inaccessible: + error("Key %d is inaccessible (%m)\n", params.key_id); + +} /* end main() */ + +/*****************************************************************************/ +/* + * determine the action to perform + */ +static void lookup_action(struct parameters *params) +{ + if (!xlocaldirs) { + scan_conf_dir(params, "/etc/request-key.d"); + scan_conf_file(params, AT_FDCWD, "/etc/request-key.conf"); + } else { + scan_conf_dir(params, "request-key.d"); + scan_conf_file(params, AT_FDCWD, "request-key.conf"); + } + + if (cmd_len > 0) + execute_program(params, cmd); + + file_error("No matching action\n"); +} + +/*****************************************************************************/ +/* + * Scan the files in a configuration directory. + */ +static void scan_conf_dir(struct parameters *params, const char *confdir) +{ + struct dirent *d; + DIR *dir; + int l; + + debug("__ SCAN %s __\n", confdir); + + dir = opendir(confdir); + if (!dir) { + if (errno == ENOENT) + return; + error("Cannot open %s: %m\n", confdir); + } + + while ((d = readdir(dir))) { + if (d->d_name[0] == '.') + continue; + if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG) + continue; + l = strlen(d->d_name); + if (l < 5) + continue; + if (memcmp(d->d_name + l - 5, ".conf", 5) != 0) + continue; + scan_conf_file(params, dirfd(dir), d->d_name); + } + + closedir(dir); +} + +/*****************************************************************************/ +/* + * Scan the contents of a configuration file. + */ +static void scan_conf_file(struct parameters *params, int dirfd, const char *conffile) +{ + char buf[4096 + 2], *p, *q; + FILE *conf; + int fd; + + debug("__ read %s __\n", conffile); + + fd = openat(dirfd, conffile, O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + return; + error("Cannot open %s: %m\n", conffile); + } + + conf = fdopen(fd, "r"); + if (!conf) + error("Cannot open %s: %m\n", conffile); + + for (confline = 1;; confline++) { + unsigned int wildness[4] = {}; + unsigned int len; + + /* read the file line-by-line */ + if (!fgets(buf, sizeof(buf), conf)) { + if (feof(conf)) + break; + file_error("error %m\n"); + } + + len = strlen(buf); + if (len >= sizeof(buf) - 2) + line_error("Line too long\n"); + + /* ignore blank lines and comments */ + if (len == 1 || buf[0] == '#' || isspace(buf[0])) + continue; + + buf[--len] = 0; + p = buf; + + /* attempt to match the op */ + q = p; + while (*p && !isspace(*p)) p++; + if (!*p) + goto syntax_error; + *p = 0; + + if (!match(q, p - q, params->op, params->oplen, &wildness[0])) + continue; + + p++; + + /* attempt to match the type */ + while (isspace(*p)) p++; + if (!*p) + goto syntax_error; + + q = p; + while (*p && !isspace(*p)) p++; + if (!*p) + goto syntax_error; + *p = 0; + + if (!match(q, p - q, params->key_type, params->ktlen, &wildness[1])) + continue; + + p++; + + /* attempt to match the description */ + while (isspace(*p)) p++; + if (!*p) + goto syntax_error; + + q = p; + while (*p && !isspace(*p)) p++; + if (!*p) + goto syntax_error; + *p = 0; + + if (!match(q, p - q, params->key_desc, params->kdlen, &wildness[2])) + continue; + + p++; + + /* attempt to match the callout info */ + while (isspace(*p)) p++; + if (!*p) + goto syntax_error; + + q = p; + while (*p && !isspace(*p)) p++; + if (!*p) + goto syntax_error; + *p = 0; + + if (!match(q, p - q, params->callout_info, params->cilen, &wildness[3])) + continue; + + p++; + + /* we've got a match */ + while (isspace(*p)) p++; + if (!*p) + goto syntax_error; + + debug("%s:%d: Line matches '%s' (%u,%u,%u,%u)\n", + conffile, confline, p, + wildness[0], wildness[1], wildness[2], wildness[3]); + + if (wildness[0] < cmd_wildness[0] || + (wildness[0] == cmd_wildness[0] && + wildness[1] < cmd_wildness[1]) || + (wildness[0] == cmd_wildness[0] && + wildness[1] == cmd_wildness[1] && + wildness[2] < cmd_wildness[2]) || + (wildness[0] == cmd_wildness[0] && + wildness[1] == cmd_wildness[1] && + wildness[2] == cmd_wildness[2] && + wildness[3] < cmd_wildness[3]) + ) { + memcpy(cmd_wildness, wildness, sizeof(cmd_wildness)); + cmd_len = len - (p - buf); + cmd_confline = confline; + debug("%s:%d: Prefer command (%u,%u,%u,%u)\n", + conffile, confline, + wildness[0], wildness[1], wildness[2], wildness[3]); + memcpy(cmd, p, cmd_len + 1); + strcpy(cmd_conffile, conffile); + } + } + + fclose(conf); + return; + +syntax_error: + line_error("Syntax error\n"); +} + +/*****************************************************************************/ +/* + * attempt to match a datum to a pattern + * - one asterisk is allowed anywhere in the pattern to indicate a wildcard + * - returns true if matched, false if not + * - adds the total number of chars skipped by wildcard to *_wildness + */ +static int match(const char *pattern, int plen, const char *datum, int dlen, + unsigned int *_wildness) +{ + const char *asterisk; + int n; + + if (verbosity >= 2) + debug("match(%*.*s,%*.*s)", plen, plen, pattern, dlen, dlen, datum); + + asterisk = memchr(pattern, '*', plen); + if (!asterisk) { + /* exact match only if no wildcard */ + if (plen == dlen && memcmp(pattern, datum, dlen) == 0) + goto yes; + goto no; + } + + /* the datum mustn't be shorter than the pattern without the asterisk */ + if (dlen < plen - 1) + goto no; + + n = asterisk - pattern; + if (n == 0) { + /* wildcard at beginning of pattern */ + pattern++; + if (!*pattern) + goto yes_wildcard; /* "*" matches everything */ + + /* match the end of the datum */ + if (memcmp(pattern, datum + (dlen - (plen - 1)), plen - 1) == 0) + goto yes_wildcard; + goto no; + } + + /* need to match beginning of datum for "abc*" and "abc*def" */ + if (memcmp(pattern, datum, n) != 0) + goto no; + + if (!asterisk[1]) + goto yes_wildcard; /* "abc*" matches */ + + /* match the end of the datum */ + asterisk++; + n = plen - n - 1; + if (memcmp(pattern, datum + (dlen - n), n) == 0) + goto yes_wildcard; + +no: + if (verbosity >= 2) + debug(" = no\n"); + return 0; + +yes: + if (verbosity >= 2) + debug(" = yes (w=0)\n"); + return 1; + +yes_wildcard: + *_wildness += dlen - (plen - 1); + if (verbosity >= 2) + debug(" = yes (w=%u)\n", dlen - (plen - 1)); + return 1; + +} /* end match() */ + +/*****************************************************************************/ +/* + * execute a program to deal with a key + */ +static void execute_program(struct parameters *params, char *cmdline) +{ + char *argv[256]; + char *prog, *p, *q; + int argc, pipeit; + + debug("execute_program('%s','%s')\n", params->callout_info, cmdline); + + /* if the commandline begins with a bar, then we pipe the callout data into it and read + * back the payload data + */ + pipeit = 0; + + if (cmdline[0] == '|') { + pipeit = 1; + cmdline++; + } + + /* extract the path to the program to run */ + prog = p = cmdline; + while (*p && !isspace(*p)) p++; +// if (!*p) +// line_error("No command path\n"); +// *p++ = 0; + if (*p) + *p++ = 0; + + argv[0] = strrchr(prog, '/') + 1; + + /* extract the arguments */ + for (argc = 1; p; argc++) { + while (isspace(*p)) p++; + if (!*p) + break; + + if (argc >= 254) + line_error("Too many arguments\n"); + argv[argc] = q = p; + + while (*p && !isspace(*p)) p++; + + if (*p) + *p++ = 0; + else + p = NULL; + + debug("argv[%d]: '%s'\n", argc, argv[argc]); + + if (*q != '%') + continue; + + /* it's a macro */ + q++; + if (!*q) + line_error("Missing macro name\n"); + + if (*q == '%') { + /* it's actually an anti-macro escape "%%..." -> "%..." */ + argv[argc]++; + continue; + } + + /* single character macros */ + if (!q[1]) { + switch (*q) { + case 'o': argv[argc] = params->op; continue; + case 'k': argv[argc] = params->key; continue; + case 't': argv[argc] = params->key_type; continue; + case 'd': argv[argc] = params->key_desc; continue; + case 'c': argv[argc] = params->callout_info; continue; + case 'u': argv[argc] = params->uid; continue; + case 'g': argv[argc] = params->gid; continue; + case 'T': argv[argc] = params->thread_keyring; continue; + case 'P': argv[argc] = params->process_keyring; continue; + case 'S': argv[argc] = params->session_keyring; continue; + default: + line_error("Unsupported macro\n"); + } + } + + /* keysub macro */ + if (*q == '{') { + key_serial_t keysub; + void *tmp; + char *ksdesc, *end, *subdata; + int ret, loop; + + /* extract type and description */ + q++; + ksdesc = strchr(q, ':'); + if (!ksdesc) + line_error("Keysub macro lacks ':'\n"); + *ksdesc++ = 0; + end = strchr(ksdesc, '}'); + if (!end) + line_error("Unterminated keysub macro\n"); + + *end++ = 0; + if (*end) + line_error("Keysub macro has trailing rubbish\n"); + + debug("Keysub: %s key \"%s\"\n", q, ksdesc); + + if (!q[0]) + line_error("Keysub type empty\n"); + + if (!ksdesc[0]) + line_error("Keysub description empty\n"); + + /* look up the key in the requestor's keyrings, but fail immediately if the + * key is not found rather than invoking /sbin/request-key again + */ + keysub = request_key(q, ksdesc, NULL, 0); + if (keysub < 0) + line_error("Keysub key not found: %m\n"); + + ret = keyctl_read_alloc(keysub, &tmp); + if (ret < 0) + line_error("Can't read keysub %d data: %m\n", keysub); + subdata = tmp; + + for (loop = 0; loop < ret; loop++) + if (!isprint(subdata[loop])) + error("keysub %d data not printable ('%02hhx')\n", + keysub, subdata[loop]); + + argv[argc] = subdata; + continue; + } + } + + if (argc == 0) + line_error("No arguments\n"); + + argv[argc] = NULL; + + if (verbosity) { + char **ap; + + debug("%s %s\n", pipeit ? "PipeThru" : "Run", prog); + for (ap = argv; *ap; ap++) + debug("- argv[%td] = \"%s\"\n", ap - argv, *ap); + } + + /* become the same UID/GID as the key requesting process */ + //setgid(atoi(xuid)); + //setuid(atoi(xgid)); + + /* if the last argument is a single bar, we spawn off the program dangling on the end of + * three pipes and read the key material from the program, otherwise we just exec + */ + if (debug_mode) { + printf("-- exec disabled --\n"); + exit(0); + } + + if (pipeit) + pipe_to_program(params, prog, argv); + + /* attempt to execute the command */ + execv(prog, argv); + + line_error("Failed to execute '%s': %m\n", prog); + +} /* end execute_program() */ + +/*****************************************************************************/ +/* + * pipe the callout information to the specified program and retrieve the + * payload data over another pipe + */ +static void pipe_to_program(struct parameters *params, char *prog, char **argv) +{ + char errbuf[512], payload[32768 + 1], *pp, *pc, *pe; + int ipi[2], opi[2], epi[2], childpid; + int ifl, ofl, efl, npay, ninfo, espace, tmp; + + debug("pipe_to_program(%s -> %s)", params->callout_info, prog); + + if (pipe(ipi) < 0 || pipe(opi) < 0 || pipe(epi) < 0) + error("pipe failed: %m"); + + childpid = fork(); + if (childpid == -1) + error("fork failed: %m"); + + if (childpid == 0) { + /* child process */ + if (dup2(ipi[0], 0) < 0 || + dup2(opi[1], 1) < 0 || + dup2(epi[1], 2) < 0) + error("dup2 failed: %m"); + close(ipi[0]); + close(ipi[1]); + close(opi[0]); + close(opi[1]); + close(epi[0]); + close(epi[1]); + + execv(prog, argv); + line_error("Failed to execute '%s': %m\n", prog); + } + + /* parent process */ + close(ipi[0]); + close(opi[1]); + close(epi[1]); + +#define TOSTDIN ipi[1] +#define FROMSTDOUT opi[0] +#define FROMSTDERR epi[0] + + ifl = fcntl(TOSTDIN, F_GETFL); + ofl = fcntl(FROMSTDOUT, F_GETFL); + efl = fcntl(FROMSTDERR, F_GETFL); + if (ifl < 0 || ofl < 0 || efl < 0) + error("fcntl/F_GETFL failed: %m"); + + ifl |= O_NONBLOCK; + ofl |= O_NONBLOCK; + efl |= O_NONBLOCK; + + if (fcntl(TOSTDIN, F_SETFL, ifl) < 0 || + fcntl(FROMSTDOUT, F_SETFL, ofl) < 0 || + fcntl(FROMSTDERR, F_SETFL, efl) < 0) + error("fcntl/F_SETFL failed: %m"); + + ninfo = params->cilen; + pc = params->callout_info; + + npay = sizeof(payload); + pp = payload; + + espace = sizeof(errbuf); + pe = errbuf; + + do { + fd_set rfds, wfds; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + if (TOSTDIN != -1) { + if (ninfo > 0) { + FD_SET(TOSTDIN, &wfds); + } + else { + close(TOSTDIN); + TOSTDIN = -1; + continue; + } + } + + if (FROMSTDOUT != -1) + FD_SET(FROMSTDOUT, &rfds); + + if (FROMSTDERR != -1) + FD_SET(FROMSTDERR, &rfds); + + tmp = TOSTDIN > FROMSTDOUT ? TOSTDIN : FROMSTDOUT; + tmp = tmp > FROMSTDERR ? tmp : FROMSTDERR; + tmp++; + + debug("select r=%d,%d w=%d m=%d\n", FROMSTDOUT, FROMSTDERR, TOSTDIN, tmp); + + tmp = select(tmp, &rfds, &wfds, NULL, NULL); + if (tmp < 0) + error("select failed: %m\n"); + + if (TOSTDIN != -1 && FD_ISSET(TOSTDIN, &wfds)) { + tmp = write(TOSTDIN, pc, ninfo); + if (tmp < 0) { + if (errno != EPIPE) + error("write failed: %m\n"); + + debug("EPIPE"); + ninfo = 0; + } + else { + debug("wrote %d\n", tmp); + + pc += tmp; + ninfo -= tmp; + } + } + + if (FROMSTDOUT != -1 && FD_ISSET(FROMSTDOUT, &rfds)) { + tmp = read(FROMSTDOUT, pp, npay); + if (tmp < 0) + error("read failed: %m\n"); + + debug("read %d\n", tmp); + + if (tmp == 0) { + close(FROMSTDOUT); + FROMSTDOUT = -1; + } + else { + pp += tmp; + npay -= tmp; + + if (npay == 0) + error("Too much data read from query program\n"); + } + } + + if (FROMSTDERR != -1 && FD_ISSET(FROMSTDERR, &rfds)) { + char *nl; + + tmp = read(FROMSTDERR, pe, espace); + if (tmp < 0) + error("read failed: %m\n"); + + debug("read err %d\n", tmp); + + if (tmp == 0) { + close(FROMSTDERR); + FROMSTDERR = -1; + continue; + } + + pe += tmp; + espace -= tmp; + + while ((nl = memchr(errbuf, '\n', pe - errbuf))) { + int n, rest; + + nl++; + n = nl - errbuf; + + if (verbosity) + fprintf(stderr, "Child: %*.*s", n, n, errbuf); + + if (!xnolog) { + openlog("request-key", 0, LOG_AUTHPRIV); + syslog(LOG_ERR, "Child: %*.*s", n, n, errbuf); + closelog(); + } + + rest = pe - nl; + if (rest > 0) { + memmove(errbuf, nl, rest); + pe -= n; + espace += n; + } + else { + pe = errbuf; + espace = sizeof(errbuf); + } + } + + if (espace == 0) { + int n = sizeof(errbuf); + + if (verbosity) + fprintf(stderr, "Child: %*.*s", n, n, errbuf); + + if (!xnolog) { + openlog("request-key", 0, LOG_AUTHPRIV); + syslog(LOG_ERR, "Child: %*.*s", n, n, errbuf); + closelog(); + } + + pe = errbuf; + espace = sizeof(errbuf); + } + } + + } while (TOSTDIN != -1 || FROMSTDOUT != -1 || FROMSTDERR != -1); + + /* wait for the program to exit */ + if (waitpid(childpid, &tmp, 0) != childpid) + error("wait for child failed: %m\n"); + + /* if the process exited non-zero or died on a signal, then we call back in to ourself to + * decide on negation + * - this is not exactly beautiful but the quickest way of having configurable negation + * settings + */ + if (WIFEXITED(tmp) && WEXITSTATUS(tmp) != 0) { + if (norecurse) + error("child exited %d\n", WEXITSTATUS(tmp)); + + norecurse = 1; + debug("child exited %d\n", WEXITSTATUS(tmp)); + params->op = "negate"; + lookup_action(params); + } + + if (WIFSIGNALED(tmp)) { + if (norecurse) + error("child died on signal %d\n", WTERMSIG(tmp)); + + norecurse = 1; + params->op = "negate"; + lookup_action(params); + } + + /* attempt to instantiate the key */ + debug("instantiate with %td bytes\n", pp - payload); + + if (keyctl_instantiate(params->key_id, payload, pp - payload, 0) < 0) + error("instantiate key failed: %m\n"); + + debug("instantiation successful\n"); + exit(0); + +} /* end pipe_to_program() */ diff --git a/request-key.conf b/request-key.conf new file mode 100644 index 0000000000..ff16a950cd --- /dev/null +++ b/request-key.conf @@ -0,0 +1,41 @@ +############################################################################### +# +# Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# +############################################################################### + + +############################################################################### +# +# We can run programs or scripts +# - Macro substitutions in arguments: +# %%... %... +# %o operation name +# %k ID of key being operated upon +# %t type of key being operated upon +# %d description of key being operated upon +# %c callout info +# %u UID of requestor +# %g GID of requestor +# %T thread keyring of requestor (may be 0) +# %P process keyring of requestor (may be 0) +# %S session keyring of requestor (may be the user's default session) +# +################################################################################ + +#OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ... +#====== ======= =============== =============== =============================== +create dns_resolver * * /sbin/key.dns_resolver %k +create user debug:* negate /bin/keyctl negate %k 30 %S +create user debug:* rejected /bin/keyctl reject %k 30 %c %S +create user debug:* expired /bin/keyctl reject %k 30 %c %S +create user debug:* revoked /bin/keyctl reject %k 30 %c %S +create user debug:loop:* * |/bin/cat +create user debug:* * /usr/share/keyutils/request-key-debug.sh %k %d %c %S +negate * * * /bin/keyctl negate %k 30 %S diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000000..838aea22de --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,76 @@ +# Copyright (c) 2015 Red Hat, Inc. All rights reserved. This copyrighted material +# is made available to anyone wishing to use, modify, copy, or +# redistribute it subject to the terms and conditions of the GNU General +# Public License v.2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Author: David Howells +# Updated to new Make model by Bill Peck + +# The toplevel namespace within which the test lives. +TOPLEVEL_NAMESPACE=/kernel + +# The name of the package under test: +PACKAGE_NAME=keyutils + +# The path of the test below the package: +RELATIVE_PATH=testsuite + +# Version of the Test. Used with make tag. +export TESTVERSION=1.3 + +# The combined namespace of the test. +export TEST=$(TOPLEVEL_NAMESPACE)/$(PACKAGE_NAME)/$(RELATIVE_PATH) + +.PHONY: all install download clean + +TESTS = $(shell /usr/bin/find . -name runtest.sh | \ + /bin/sed -e 's/runtest.sh//g;s/^\.\///;s/\/$$//') + +BUILT_FILES= +FILES=$(METADATA) *.sh Makefile PURPOSE bugzillas keyctl + +run: $(FILES) build + bash runtest.sh $(TESTS) + +build: $(BUILT_FILES) + +clean: + rm -f *~ *.rpm $(BUILT_FILES) + find * -name test.out -delete + +# You may need to add other targets e.g. to build executables from source code +# Add them here: + + +# Include Common Makefile +ifneq ($(wildcard /usr/share/rhts/lib/rhts-make.include),) +include /usr/share/rhts/lib/rhts-make.include + +# Generate the testinfo.desc here: +$(METADATA): Makefile + @touch $(METADATA) + @echo "Owner: David Howells " > $(METADATA) + @echo "Name: $(TEST)" >> $(METADATA) + @echo "Path: $(TEST_DIR)" >> $(METADATA) + @echo "License: Unknown" >> $(METADATA) + @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) + @echo "Description: testsuite to verify keyutils ">> $(METADATA) + @echo "TestTime: 30m" >> $(METADATA) + @echo "RunFor: $(PACKAGE_NAME)" >> $(METADATA) + @echo "Requires: $(PACKAGE_NAME)" >> $(METADATA) + @echo "Requires: redhat-lsb-core" >> $(METADATA) + @echo "Releases: -RHEL2.1 -RHEL3" >> $(METADATA) + @echo "Type: Tier1" >> $(METADATA) + @echo "Type: KernelTier1" >> $(METADATA) + @echo "Destructive: no" >> $(METADATA) + rhts-lint $(METADATA) + +endif diff --git a/tests/PURPOSE b/tests/PURPOSE new file mode 100644 index 0000000000..064e775c6a --- /dev/null +++ b/tests/PURPOSE @@ -0,0 +1,82 @@ +The purpose of this testsuite is to do negative and positive testing against +the keyutils package. +Sub Test Description +------------------ ----------------------------------------------------- +/listing/noargs Check list/rlist subcommands fail with the wrong + number of arguments +/listing/bad-args Check list/rlist subcommands fail with bad arguments +/listing/valid Check list/rlist subcommands work +/show/noargs Check show subcommand works with no arguments +/reading/noargs Check read/pipe/print subcommands fail with the wrong + number of arguments +/reading/bad-args Check read/pipe/print subcommands fail with bad + arguments +/reading/valid Check read/pipe/print subcommands work +/pupdate/noargs Check pupdate subcommand fails with the wrong number + of arguments +/pupdate/bad-args Check pupdate subcommand fails with bad arguments +/pupdate/userupdate Check pupdate subcommand works for user defined keys +/newring/noargs Check newring subcommand fails with the wrong number + of arguments +/newring/bad-args Check newring subcommand fails with a bad arguments +/newring/valid Check newring subcommand works +/session/bad-args Check session subcommand fails with bad arguments +/session/valid Check session subcommand works +/clear/noargs Check clear subcommand fails with the wrong number of + arguments +/clear/bad-args Check clear subcommand fails with a bad arguments +/clear/valid Check clear subcommand works +/instantiating/noargs Check instantiate/negate subcommands fail with the + wrong number of arguments +/instantiating/bad-args Check instantiate/negate subcommands fail with bad + arguments +/permitting/noargs Check chown/chgrp/setperm subcommands fail with the + wrong number of arguments +/permitting/bad-args Check chown/chgrp/setperm subcommands fail with bad + arguments +/permitting/valid Check chown/chgrp/setperm subcommands work +/describing/noargs Check describe/rdescribe subcommands fail with the + wrong number of arguments +/describing/bad-args Check describe/rdescribe subcommands fail with bad + arguments +/describing/valid Check describe/rdescribe subcommands work +/noargs Check keyutils with no args gives format list +/revoke/noargs Check revoke subcommand fails with the wrong number of + arguments +/revoke/bad-args Check revoke subcommand fails with a bad arguments +/revoke/valid Check revoke subcommand works +/padd/noargs Check padd subcommand fails with the wrong number of + arguments +/padd/bad-args Check padd subcommand fails with bad arguments +/padd/useradd Check padd subcommand works +/timeout/noargs Check timeout subcommand fails with the wrong number + of arguments +/timeout/bad-args Check timeout subcommand fails with a bad arguments +/timeout/valid Check timeout subcommand works +/update/noargs Check update subcommand fails with the wrong number of + arguments +/update/bad-args Check update subcommand fails with bad arguments +/update/userupdate Check update subcommand works for user defined keys +/search/noargs Check search subcommand fails with the wrong number of + arguments +/search/bad-args Check search subcommand fails with a bad arguments +/search/valid Check search subcommand works +/link/recursion Check link subcommand handles recursive links correctly +/link/noargs Check link subcommand fails with the wrong number of + arguments +/link/bad-args Check link subcommand fails with bad arguments +/link/valid Check link subcommand works +/add/noargs Check add subcommand fails with the wrong number of + arguments +/add/bad-args Check add subcommand fails with a bad arguments +/add/useradd Check add subcommand works +/requesting/piped Check request/prequest2 subcommands work +/requesting/noargs Check request/request2 subcommands fail with the + wrong number of arguments +/requesting/bad-args Check request/request2 subcommands fail with bad + arguments +/requesting/valid Check request/request2 subcommands work +/unlink/noargs Check unlink subcommand fails with the wrong number of + arguments +/unlink/bad-args Check unlink subcommand fails with a bad arguments +/unlink/valid Check unlink subcommand works diff --git a/tests/bugzillas/bz1031154/runtest.sh b/tests/bugzillas/bz1031154/runtest.sh new file mode 100644 index 0000000000..d90afb4f21 --- /dev/null +++ b/tests/bugzillas/bz1031154/runtest.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Test for https://bugzilla.redhat.com/show_bug.cgi?id=1031154 + +. ../../prepare.inc.sh +. ../../toolbox.inc.sh + +# We intentionally generate AVCs so the test system shouldn't fail us +# because the AVCs were generated. +export AVC_ERROR=+no_avc_check +export RHTS_OPTION_STRONGER_AVC= + +# ---- do the actual testing ---- + +result=PASS + +if [ $have_big_key_type = 0 ] +then + toolbox_skip_test $TEST "SKIPPING TEST DUE TO LACK OF BIG_KEY TYPE" + exit 0 +fi + +require_selinux +require_command getenforce +require_command setenforce +require_command runcon +require_command ausearch + +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# we need a reference time to scan the audit log from so as not to pick up old +# results from this test. +base_date=`date +"%x@%X"` +base_time=${base_date#*@} +base_date=${base_date%@*} +sleep 1 + +# reset the permissive audit log autocancel thing +load_policy + +# we need to be in permissive mode +marker "ENTER SELINUX PERMISSIVE MODE" + +mode=`getenforce` + +if [ "$mode" != "Permissive" ] +then + echo setenforce Permissive >>$OUTPUTFILE + if ! setenforce Permissive + then + failed + fi +fi + +# create a big key to probe +marker "CREATE BIG KEY" +pcreate_key_by_size 8192 big_key test-key @s +expect_keyid id + +# check the big key is file backed and the right size +marker "CHECK BIG KEY" +xid=`printf %08x $id` + +pk=`cat /proc/keys | grep "^$xid.*test-key: 8192 \\[file\\]"` +echo $pk >>$OUTPUTFILE +if [ -z "$pk" ] +then + echo "+++ Incorrectly created key" >>$OUTPUTFILE + cat /proc/keys | grep "^$xid" >>$OUTPUTFILE + failed +fi + +# use a separate context to access the key +marker "ACCESS INTERCONTEXT" + +echo runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $id >>$OUTPUTFILE +if ! runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $id >/dev/null 2>>$OUTPUTFILE +then + failed +fi + +# examine the audit logs +marker "EXAMINE AUDIT LOGS" + +echo ausearch -m AVC -i --subject httpd_t -ts $base_date $base_time \| audit2allow \| grep '-P "allow httpd_t user_tmpfs_t:file [{] (open |read )+[}];"' >>$OUTPUTFILE +if ausearch -m AVC -i --subject httpd_t -ts $base_date $base_time 2>>$OUTPUTFILE | audit2allow 2>>$OUTPUTFILE | grep -P "allow httpd_t user_tmpfs_t:file [{] (open |read )+[}];" +then + failed +fi + +marker "RESTORE SELINUX MODE" +if [ "$mode" != "Permissive" ] +then + echo setenforce $mode >>$OUTPUTFILE + if ! setenforce $mode + then + failed + fi +fi + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/bugzillas/bz1033467/runtest.sh b/tests/bugzillas/bz1033467/runtest.sh new file mode 100644 index 0000000000..54ec293dc9 --- /dev/null +++ b/tests/bugzillas/bz1033467/runtest.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Test for https://bugzilla.redhat.com/show_bug.cgi?id=1033467 + +. ../../prepare.inc.sh +. ../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD SANDBOX KEYRING" +create_keyring sandbox @s +expect_keyid sandbox + +# create a bunch of nested keyrings in the sandbox +marker "ADD NESTED KEYRINGS" +declare -a ring +for ((i=0; i<=16; i++)) +do + create_keyring ring$i $sandbox + expect_keyid "ring[$i]" +done + +# create a key in each of those keyrings +marker "ADD KEYS" +keys="" +for ((i=0; i<=16; i++)) +do + create_key user a$i a ${ring[$i]} + expect_keyid id + keys="$keys $id" +done + +# search for the added keys, beginning at sandbox and exercising the nesting +marker "SEARCH KEYS" +keys2="" +for ((i=0; i<=16; i++)) +do + search_for_key $sandbox user a$i + expect_keyid id + keys2="$keys2 $id" +done + +marker "COMPARE KEY LISTS" +if [ "$keys" != "$keys2" ] +then + echo "Key lists differ" >>$OUTPUTFILE + echo List 1: "\"$keys\"" >>$OUTPUTFILE + echo List 2: "\"$keys2\"" >>$OUTPUTFILE + failed +fi + +# search for some unadded keys and make sure we get an error +marker "SEARCH MISSES" +for ((i=17; i<=20; i++)) +do + search_for_key --fail $sandbox user a$i + expect_error ENOKEY +done + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/bugzillas/bz1071346/runtest.sh b/tests/bugzillas/bz1071346/runtest.sh new file mode 100644 index 0000000000..45f0a02e86 --- /dev/null +++ b/tests/bugzillas/bz1071346/runtest.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Test for https://bugzilla.redhat.com/show_bug.cgi?id=1071346 + +. ../../prepare.inc.sh +. ../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD SANDBOX KEYRING" +create_keyring sandbox @s +expect_keyid sandbox + +# Add a second keyring of the same name into the sandbox +marker "ADD SECOND SANDBOX KEYRING" +create_keyring sandbox $sandbox +expect_keyid second + +# Now try and link keyrings together in ways that should fail +marker "CHECK NO LINK SESSION TO SECOND" +link_key --fail @s $second +expect_error EDEADLK +marker "CHECK NO LINK SANDBOX TO SECOND" +link_key --fail $sandbox $second +expect_error EDEADLK +marker "CHECK NO LINK SECOND TO SECOND" +link_key --fail $second $second +expect_error EDEADLK + +# Add another keyring into sandbox and stick a third sandbox keyring in that +marker "ADD SIDE KEYRING" +create_keyring side $sandbox +expect_keyid side +marker "ADD THIRD SANDBOX KEYRING" +create_keyring sandbox $side +expect_keyid third + +# Make sure we can't link the session keyring, the sandbox, the side +# keyring or the third keyring itself into the third keyring. +marker "CHECK NO LINK SESSION TO THIRD" +link_key --fail @s $third +expect_error EDEADLK +marker "CHECK NO LINK SANDBOX TO THIRD" +link_key --fail $sandbox $third +expect_error EDEADLK +marker "CHECK NO LINK SIDE TO THIRD" +link_key --fail $side $third +expect_error EDEADLK +marker "CHECK NO LINK THIRD TO THIRD" +link_key --fail $sandbox $third +expect_error EDEADLK + +# We should, however, be able to link second to third but not then +# third to second +marker "CHECK LINK SECOND TO THIRD" +link_key $second $third +marker "CHECK NO LINK THIRD TO SECOND" +link_key --fail $third $second +expect_error EDEADLK + +# We can then detach the link we just made and check the reverse +# linkage. +marker "UNLINK SECOND FROM THIRD" +unlink_key $second $third +marker "CHECK LINK THIRD TO SECOND" +link_key $third $second +marker "CHECK NO LINK SECOND TO THIRD" +link_key --fail $second $third +expect_error EDEADLK + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/add/bad-args/runtest.sh b/tests/keyctl/add/bad-args/runtest.sh new file mode 100644 index 0000000000..38795fa0ac --- /dev/null +++ b/tests/keyctl/add/bad-args/runtest.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that an empty key type fails correctly +marker "CHECK EMPTY KEY TYPE" +create_key --fail "" wibble stuff @p +expect_error EINVAL + +# check that an unsupported key type fails correctly +marker "CHECK UNSUPPORTED KEY TYPE" +create_key --fail lizardsgizzards wibble stuff @p +expect_error ENODEV + +# check that an invalid key type fails correctly +marker "CHECK INVALID KEY TYPE" +create_key --fail .user wibble stuff @p +expect_error EPERM + +# check that an maximum length invalid key type fails correctly +marker "CHECK MAXLEN KEY TYPE" +create_key --fail $maxtype wibble stuff @p +expect_error ENODEV + +# check that an overlong key type fails correctly +marker "CHECK OVERLONG KEY TYPE" +create_key --fail a$maxtype wibble stuff @p +expect_error EINVAL + +# check that creation of a keyring with non-empty payload fails correctly +marker "CHECK ADD KEYRING WITH PAYLOAD" +create_key --fail keyring wibble a @p +expect_error EINVAL + +# check that an max length key description works correctly (PAGE_SIZE inc NUL) +if [ $PAGE_SIZE -lt $maxsquota ] +then + marker "CHECK MAXLEN DESC" + create_key user $maxdesc stuff @p + expect_keyid keyid +else + marker "CHECK MAXLEN DESC FAILS WITH EDQUOT" + create_key --fail user $maxdesc stuff @p + expect_error EDQUOT +fi + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong key description fails correctly (>4095 inc NUL) + marker "CHECK OVERLONG DESC" + create_key --fail user a$maxdesc stuff @p + expect_error EINVAL +fi + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +create_key --fail user wibble stuff 0 +expect_error EINVAL + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/add/noargs/runtest.sh b/tests/keyctl/add/noargs/runtest.sh new file mode 100644 index 0000000000..d5abb7dd00 --- /dev/null +++ b/tests/keyctl/add/noargs/runtest.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl add + +# check that one argument fails correctly +marker "ADD ONE ARG" +expect_args_error keyctl add user + +# check that two arguments fail correctly +marker "ADD TWO ARGS" +expect_args_error keyctl add user wibble + +# check that three arguments fail correctly +marker "ADD THREE ARGS" +expect_args_error keyctl add user wibble stuff + +# check that five arguments fail correctly +marker "ADD FIVE ARGS" +expect_args_error keyctl add user wibble stuff @s x + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/add/useradd/runtest.sh b/tests/keyctl/add/useradd/runtest.sh new file mode 100644 index 0000000000..031241cb09 --- /dev/null +++ b/tests/keyctl/add/useradd/runtest.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that we can add a user key to the session keyring +marker "ADD USER KEY" +create_key user wibble stuff @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + +# check that we can update a user key +marker "UPDATE USER KEY" +create_key user wibble lizard @s + +# check we get the same key ID back +expect_keyid keyid2 + +if [ "x$keyid" != "x$keyid2" ] +then + failed +fi + +# read back what we changed it to +marker "PRINT UPDATED PAYLOAD" +print_key $keyid +expect_payload payload "lizard" + +# attempt to add a key to that non-keyring key +marker "ADD KEY TO NON-KEYRING" +create_key --fail user lizard gizzards $keyid +expect_error ENOTDIR + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid @s + +keyctl show + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/clear/bad-args/runtest.sh b/tests/keyctl/clear/bad-args/runtest.sh new file mode 100644 index 0000000000..feb89f652c --- /dev/null +++ b/tests/keyctl/clear/bad-args/runtest.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK CLEAR BAD KEY ID" +clear_keyring --fail 0 +expect_error EINVAL + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# check that a non-keyring ID fails correctly +marker "CHECK CLEAR NON-KEYRING KEY" +clear_keyring --fail $keyid +expect_error ENOTDIR + +# dispose of the key we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK CLEAR NON-EXISTENT KEY ID" +clear_keyring --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/clear/noargs/runtest.sh b/tests/keyctl/clear/noargs/runtest.sh new file mode 100644 index 0000000000..7bcfa892e6 --- /dev/null +++ b/tests/keyctl/clear/noargs/runtest.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl clear + +# check that one argument fails correctly +marker "TWO ARGS" +expect_args_error keyctl clear 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/clear/valid/runtest.sh b/tests/keyctl/clear/valid/runtest.sh new file mode 100644 index 0000000000..9cb35ef188 --- /dev/null +++ b/tests/keyctl/clear/valid/runtest.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# validate the new keyring's name and type +marker "VALIDATE KEYRING" +describe_key $keyringid +expect_key_rdesc rdesc 'keyring@.*@wibble' + +# check that we have an empty keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# clear the empty keyring +marker "CLEAR EMPTY KEYRING" +clear_keyring $keyringid + +# check that it's empty again +marker "LIST KEYRING 2" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# clear the keyring +marker "CLEAR KEYRING WITH ONE" +clear_keyring $keyringid + +# check that it's now empty again +marker "LIST KEYRING 3" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick forty keys in the keyring +marker "ADD FORTY KEYS" +keys="" +for ((i=0; i<40; i++)) + do + create_key user lizard$i gizzard$i $keyringid + expect_keyid x + keys="$keys $x" + list_keyring $keyringid + expect_keyring_rlist rlist $x +done + +marker "CHECK KEYRING CONTENTS" +list_keyring $keyringid +for i in $keys +do + expect_keyring_rlist rlist $i +done + +marker "SHOW KEYRING" +if ! keyctl show >>$OUTPUTFILE 2>&1 +then + failed +fi + +# clear the keyring +marker "CLEAR KEYRING WITH ONE" +clear_keyring $keyringid + +# check that it's now empty yet again +marker "LIST KEYRING 4" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# remove the keyring we added +marker "UNLINK KEY" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/describing/bad-args/runtest.sh b/tests/keyctl/describing/bad-args/runtest.sh new file mode 100644 index 0000000000..a49ee5215b --- /dev/null +++ b/tests/keyctl/describing/bad-args/runtest.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +describe_key --fail 0 +expect_error EINVAL +pretty_describe_key --fail 0 +expect_error EINVAL + +# create a key +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# dispose of the key +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK NON-EXISTENT KEY ID" +describe_key --fail $keyid +expect_error ENOKEY +pretty_describe_key --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/describing/noargs/runtest.sh b/tests/keyctl/describing/noargs/runtest.sh new file mode 100644 index 0000000000..fac4c498de --- /dev/null +++ b/tests/keyctl/describing/noargs/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl describe +expect_args_error keyctl rdescribe + +marker "TWO ARGS" +expect_args_error keyctl describe 0 0 + +marker "THREE ARGS" +expect_args_error keyctl rdescribe 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/describing/valid/runtest.sh b/tests/keyctl/describing/valid/runtest.sh new file mode 100644 index 0000000000..e327e4ba41 --- /dev/null +++ b/tests/keyctl/describing/valid/runtest.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# validate the new keyring's name and type +marker "VALIDATE KEYRING" +describe_key $keyringid +expect_key_rdesc rdesc 'keyring@.*@wibble' + +# validate a pretty description of the keyring +marker "VALIDATE PRETTY KEYRING" +pretty_describe_key $keyringid +expect_key_rdesc pdesc " *$keyringid: [-avrwsl]* *[-0-9]* *[-0-9]* keyring: wibble" + +# check that we have an empty keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# validate the new key's name and type +marker "VALIDATE KEY" +describe_key $keyid +expect_key_rdesc rdesc 'user@.*@lizard' + +# validate a pretty description of the key +marker "VALIDATE PRETTY KEY" +pretty_describe_key $keyid +expect_key_rdesc pdesc " *$keyid: [-avrwsl]* *[0-9]* *[-0-9]* user: lizard" + +# turn off view permission on the key +marker "DISABLE VIEW PERM" +set_key_perm $keyid 0x3e0000 +describe_key --fail $keyid +expect_error EACCES + +# turn on view permission on the key +marker "REINSTATE VIEW PERM" +set_key_perm $keyid 0x3f0000 +describe_key $keyid + +# revoke the key +marker "REVOKE KEY" +revoke_key $keyid +describe_key --fail $keyid +expect_error EKEYREVOKED + +# remove the keyring we added +marker "UNLINK KEY" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/dh_compute/bad-args/runtest.sh b/tests/keyctl/dh_compute/bad-args/runtest.sh new file mode 100644 index 0000000000..7e8828b068 --- /dev/null +++ b/tests/keyctl/dh_compute/bad-args/runtest.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_dh_compute = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# Prime, generator, and key values created with: +# openssl dhparam 2048 -check -out dh.pem +# openssl genpkey -paramfile dh.pem -text +prime="\x00\xb6\x89\x4d\x8f\xf7\xaf\x56\xd4\x46\xc9\x50\xc7\xe9\x1d" +prime+="\x29\x8a\x07\x8d\xae\xa7\x79\x66\xf1\x1f\xc1\x6f\x22\x92\x11" +prime+="\x73\x7f\x1f\x39\xce\xf3\xda\xd7\x87\x2a\x53\x8f\x6c\x8f\x9a" +prime+="\x27\x6a\x7c\xf7\x7b\xb2\xd6\x3a\x87\x2a\x4d\xb9\xed\x12\xae" +prime+="\x0f\x1c\x69\xaf\x9b\xf2\xf2\xe3\x69\x1d\x36\x15\xa1\xd7\xd5" +prime+="\x77\xa8\x7d\x1c\xb4\xab\xa0\x49\x4b\xae\x0c\x24\x9b\x0c\xce" +prime+="\xef\x6b\x7a\xb9\xa7\xbe\x70\xb5\xb4\x5e\x4c\xf7\xcb\x71\xad" +prime+="\x8f\xeb\x7a\x4d\x6c\x7c\xcb\x96\xd5\x29\x8f\x0f\xee\xb4\x78" +prime+="\x77\x60\x5e\x80\xa0\x33\x86\x91\xe3\x58\x62\xf0\xf4\xcb\xb2" +prime+="\x09\xe1\x7d\xd9\xfe\xbc\xce\x4c\x21\x57\x70\x06\xce\xb1\x15" +prime+="\x7b\x18\x15\x92\xd2\xf7\x84\xba\x44\xe0\x06\xc3\x14\xdf\x53" +prime+="\x06\xbd\xbb\x17\xa0\x10\xb3\x66\x0d\x47\x93\x56\xd8\xd5\x2c" +prime+="\x5a\xf0\x14\x53\x6c\x20\x89\x7e\x76\x53\x21\x8e\x2c\x7a\x65" +prime+="\x0a\x73\xdc\x27\x58\x45\x98\xde\x92\xde\x5c\x62\x70\x67\x71" +prime+="\xfa\x2d\x67\xf6\x25\x44\x1d\x91\x1c\xa0\x3f\x21\x49\xb6\xd4" +prime+="\xc7\x6b\x5e\xcd\x98\x96\xe9\xd7\x99\xa3\xa5\x00\xec\xec\xc5" +prime+="\x19\xe3\x1b\x71\x15\x4d\x7b\x36\x1b\xd0\xdd\x15\xf7\xce\x8d" +prime+="\xfc\x63" + +generator="\x02" + +private="\x40\x94\x9d\xa2\xca\x2b\x7c\x35\x3d\xe3\x8f\xef\xb0\x6d\xdd" +private+="\x0d\x67\x47\x9a\x63\x61\xc8\x9e\x77\xb9\x80\xd2\x48\x6c\x4d" +private+="\x31\x97\x1e\xb8\x8f\x65\x72\x06\x99\x73\xe3\xae\x5a\x43\xce" +private+="\x76\xbc\xcb\x35\xea\x05\xac\x65\x38\xeb\x0e\xa6\xad\xee\x49" +private+="\x37\x60\x04\x35\xdd\x79\x40\x88\x5d\x2e\x3f\x78\xc7\x28\x08" +private+="\x34\xf8\x78\xd3\xd5\x50\xcc\x93\x05\x33\x0b\xb8\xf0\x20\x85" +private+="\xee\x6c\x23\x0d\x42\xd8\x4e\xb6\x7a\x24\x5b\x92\x81\x7f\xd1" +private+="\x54\xbc\xb1\x39\x4a\x28\x9d\x11\xaf\xb5\xa1\xe5\x0e\x13\x95" +private+="\x09\x08\xaf\x70\x75\x67\x04\xe9\xbf\x03\xdf\xf0\xe5\xd4\x90" +private+="\x74\x38\x41\xc5\x34\xcb\x7e\x2c\xf4\xb9\xf0\x49\x3a\x73\x0b" +private+="\x0d\x71\x09\x6a\x16\xbd\xc0\xe8\x52\xf1\x75\x75\x51\x34\xb2" +private+="\xb4\x11\x12\x28\x0a\x88\x21\x27\x28\xaf\xbe\x16\xd4\x17\xf3" +private+="\x18\x93\xcb\xe4\x42\xe0\x6d\x21\x2d\x8e\xfe\x22\x7a\xa0\x03" +private+="\x9a\x65\xce\x99\x81\x07\xfa\xe2\x78\x51\x1c\x6b\xf4\xd5\x99" +private+="\x32\x53\x4a\xe9\xfc\x39\xdb\x80\x63\x51\x63\xc0\x54\x66\x57" +private+="\x50\x08\x66\xd5\x46\x1c\x5f\xa3\x54\x02\x38\x32\x4a\x29\xf3" +private+="\x16\xe0\x68\xf3\xba\x17\x37\xd0\x42\xcb\x51\xa8\x97\x1b\xc7" +private+="\xa2" + +pcreate_key "-e $prime" user dh:prime @s +expect_keyid primeid + +pcreate_key "-e $generator" user dh:generator @s +expect_keyid generatorid + +pcreate_key "-e $private" user dh:private @s +expect_keyid privateid + +pcreate_key "-e \x00" logon dh:logon @s +expect_keyid logonid + +marker "CHECK WRONG KEY TYPE" +dh_compute --fail $privateid $primeid $logonid +expect_error ENOKEY +dh_compute --fail $privateid $primeid @s +expect_error EOPNOTSUPP + +marker "CHECK MISSING KEY" +dh_compute --fail $privateid $primeid 0 +expect_error ENOKEY +unlink_key --wait $generatorid @s +dh_compute --fail $privateid $primeid $generatorid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/dh_compute/noargs/runtest.sh b/tests/keyctl/dh_compute/noargs/runtest.sh new file mode 100644 index 0000000000..e761f6bf9d --- /dev/null +++ b/tests/keyctl/dh_compute/noargs/runtest.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_dh_compute = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl dh_compute + +marker "TWO ARGS" +expect_args_error keyctl dh_compute 0 0 + +marker "FOUR ARGS" +expect_args_error keyctl dh_compute 0 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/dh_compute/valid/runtest.sh b/tests/keyctl/dh_compute/valid/runtest.sh new file mode 100644 index 0000000000..5ad1d14592 --- /dev/null +++ b/tests/keyctl/dh_compute/valid/runtest.sh @@ -0,0 +1,266 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_dh_compute = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# Prime, generator, and key values created with: +# openssl dhparam 2048 -check -out dh.pem +# openssl genpkey -paramfile dh.pem -text +prime="\x00\xb6\x89\x4d\x8f\xf7\xaf\x56\xd4\x46\xc9\x50\xc7\xe9\x1d" +prime+="\x29\x8a\x07\x8d\xae\xa7\x79\x66\xf1\x1f\xc1\x6f\x22\x92\x11" +prime+="\x73\x7f\x1f\x39\xce\xf3\xda\xd7\x87\x2a\x53\x8f\x6c\x8f\x9a" +prime+="\x27\x6a\x7c\xf7\x7b\xb2\xd6\x3a\x87\x2a\x4d\xb9\xed\x12\xae" +prime+="\x0f\x1c\x69\xaf\x9b\xf2\xf2\xe3\x69\x1d\x36\x15\xa1\xd7\xd5" +prime+="\x77\xa8\x7d\x1c\xb4\xab\xa0\x49\x4b\xae\x0c\x24\x9b\x0c\xce" +prime+="\xef\x6b\x7a\xb9\xa7\xbe\x70\xb5\xb4\x5e\x4c\xf7\xcb\x71\xad" +prime+="\x8f\xeb\x7a\x4d\x6c\x7c\xcb\x96\xd5\x29\x8f\x0f\xee\xb4\x78" +prime+="\x77\x60\x5e\x80\xa0\x33\x86\x91\xe3\x58\x62\xf0\xf4\xcb\xb2" +prime+="\x09\xe1\x7d\xd9\xfe\xbc\xce\x4c\x21\x57\x70\x06\xce\xb1\x15" +prime+="\x7b\x18\x15\x92\xd2\xf7\x84\xba\x44\xe0\x06\xc3\x14\xdf\x53" +prime+="\x06\xbd\xbb\x17\xa0\x10\xb3\x66\x0d\x47\x93\x56\xd8\xd5\x2c" +prime+="\x5a\xf0\x14\x53\x6c\x20\x89\x7e\x76\x53\x21\x8e\x2c\x7a\x65" +prime+="\x0a\x73\xdc\x27\x58\x45\x98\xde\x92\xde\x5c\x62\x70\x67\x71" +prime+="\xfa\x2d\x67\xf6\x25\x44\x1d\x91\x1c\xa0\x3f\x21\x49\xb6\xd4" +prime+="\xc7\x6b\x5e\xcd\x98\x96\xe9\xd7\x99\xa3\xa5\x00\xec\xec\xc5" +prime+="\x19\xe3\x1b\x71\x15\x4d\x7b\x36\x1b\xd0\xdd\x15\xf7\xce\x8d" +prime+="\xfc\x63" + +generator="\x02" + +private="\x40\x94\x9d\xa2\xca\x2b\x7c\x35\x3d\xe3\x8f\xef\xb0\x6d\xdd" +private+="\x0d\x67\x47\x9a\x63\x61\xc8\x9e\x77\xb9\x80\xd2\x48\x6c\x4d" +private+="\x31\x97\x1e\xb8\x8f\x65\x72\x06\x99\x73\xe3\xae\x5a\x43\xce" +private+="\x76\xbc\xcb\x35\xea\x05\xac\x65\x38\xeb\x0e\xa6\xad\xee\x49" +private+="\x37\x60\x04\x35\xdd\x79\x40\x88\x5d\x2e\x3f\x78\xc7\x28\x08" +private+="\x34\xf8\x78\xd3\xd5\x50\xcc\x93\x05\x33\x0b\xb8\xf0\x20\x85" +private+="\xee\x6c\x23\x0d\x42\xd8\x4e\xb6\x7a\x24\x5b\x92\x81\x7f\xd1" +private+="\x54\xbc\xb1\x39\x4a\x28\x9d\x11\xaf\xb5\xa1\xe5\x0e\x13\x95" +private+="\x09\x08\xaf\x70\x75\x67\x04\xe9\xbf\x03\xdf\xf0\xe5\xd4\x90" +private+="\x74\x38\x41\xc5\x34\xcb\x7e\x2c\xf4\xb9\xf0\x49\x3a\x73\x0b" +private+="\x0d\x71\x09\x6a\x16\xbd\xc0\xe8\x52\xf1\x75\x75\x51\x34\xb2" +private+="\xb4\x11\x12\x28\x0a\x88\x21\x27\x28\xaf\xbe\x16\xd4\x17\xf3" +private+="\x18\x93\xcb\xe4\x42\xe0\x6d\x21\x2d\x8e\xfe\x22\x7a\xa0\x03" +private+="\x9a\x65\xce\x99\x81\x07\xfa\xe2\x78\x51\x1c\x6b\xf4\xd5\x99" +private+="\x32\x53\x4a\xe9\xfc\x39\xdb\x80\x63\x51\x63\xc0\x54\x66\x57" +private+="\x50\x08\x66\xd5\x46\x1c\x5f\xa3\x54\x02\x38\x32\x4a\x29\xf3" +private+="\x16\xe0\x68\xf3\xba\x17\x37\xd0\x42\xcb\x51\xa8\x97\x1b\xc7" +private+="\xa2" + +read -d '' public <<"EOF" +a4cf1f93 95fce03f d02aaece da1f86bd d8d77b69 29039fcc bd138c98 2483bf9c +7e4406c1 4f3cea24 6cafb29e 95095d0c 6768f13b 31babb24 6c590d92 6c343e69 +59dbd47f 65982a3b b1baa7a3 05a72054 89b6cd0d 78397962 fc834fc9 3ec0517e +c218396f 9cff860e 29078aee 6b8598b6 79325014 bb84597d f031e149 edbe1c5a +2a55fe4e bbc64a52 6da59e71 1c7ae5e0 954ba23b 9d58c423 17d84841 815708c8 +b9059987 48773eac 2244b286 cd118277 48b7ed3a 5af5cc0f 8f254190 5e16f998 +a328e894 acc343f4 66a95281 86cea6a3 93eb4fee f83c0e2e f4a00ce6 fcc9ef81 +cc4624d5 ba659411 d1ba7b5f 14a3e286 d42e6ac8 afa9f846 41cb7cb5 66965725 +EOF + +pcreate_key "-e $prime" user dh:prime @s +expect_keyid primeid + +pcreate_key "-e $generator" user dh:generator @s +expect_keyid generatorid + +pcreate_key "-e $private" user dh:private @s +expect_keyid privateid + +marker "COMPUTE DH PUBLIC KEY" +dh_compute $privateid $primeid $generatorid +expect_multiline payload "$public" + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + + +################################################################ +# Testing DH compute with KDF according to SP800-56A +# +# test vectors from http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/KASTestVectorsFFC2014.zip +################################################################ + +# SHA-256 + +# XephemCAVS +private="\x81\xb2\xc6\x5f\x5c\xba\xc0\x0b\x13\x53\xac\x38\xbd\x77\xa2\x5a" +private+="\x86\x50\xed\x48\x5e\x41\x3e\xac\x1d\x6c\x48\x85" + +# P +prime="\xa3\xcc\x62\x23\xe5\x0c\x6e\x3f\x7b\xb0\x58\x1d\xcb\x9e\x9f\xf0" +prime+="\x2c\x58\x07\x68\x32\x8a\x15\x20\x7b\x1c\x32\x31\x7f\xb7\x84\x96" +prime+="\x81\x5e\x3c\xf7\xf9\xd0\x9c\xcb\x9f\xa8\x40\xff\x47\x98\x51\x1a" +prime+="\x17\xb5\x59\x28\x72\x1e\x5d\xfb\xcc\xc5\x41\x47\xe0\xf0\x5f\x85" +prime+="\xb3\xac\x41\x0b\x6a\xe3\xf5\x9b\x79\x6f\x3f\xea\xc7\xfc\x52\x49" +prime+="\x21\x7e\xb2\xa0\x45\x88\x29\x3a\x5a\xde\x22\x78\x79\xf4\x6c\xeb" +prime+="\x56\x45\x7b\x5c\x43\x12\x93\xe5\xe1\x04\xd1\xb9\x64\xbd\x2c\xdf" +prime+="\xde\xff\xa0\x40\x49\xa9\x1e\x67\xee\x8c\x86\xe9\x44\xf0\x4f\x94" +prime+="\x4a\x30\xe3\x61\xf8\xd1\x5d\x17\xe5\x01\x0c\xab\xb4\xef\x40\xc0" +prime+="\xeb\xa5\xf4\xa2\x52\xd4\xfd\x6c\xf9\xda\xe6\x0e\x86\xe4\xb3\x00" +prime+="\x9b\x1d\xfc\x92\x66\x70\x35\x72\x61\x58\x7a\xd0\x5c\x00\xa6\xc6" +prime+="\xf0\x10\x6c\xec\x8f\xc5\x91\x31\x51\x50\x84\xa8\x70\x59\x41\x65" +prime+="\xb4\x93\x90\xdb\x2d\x00\xe7\x53\x8f\x23\x0d\x53\x2f\x4a\x4e\xca" +prime+="\x83\x09\xd7\x07\xc0\xb3\x83\x5c\xee\x04\xf3\xca\x55\x8a\x22\xc6" +prime+="\xb5\x20\xfe\x25\xde\x6f\xfa\x90\xef\xda\x49\x27\xd0\x18\x59\x4c" +prime+="\x0c\x0b\x77\x06\x73\x93\xb7\xf1\xe0\xfc\x7c\xf2\x16\xaf\xf3\x9f" + +# YephemIUT +xa="\x9a\x70\x82\x2d\x3f\x06\x12\x3d\x0e\x51\x8e\xe1\x16\x51\xe5\xf6" +xa+="\xb1\x19\xdc\x3b\x97\xd5\xb1\xc0\xa2\xa6\xf6\xde\x94\x25\x64\xba" +xa+="\x10\x06\x1e\xec\xde\xb7\x36\x9c\xa5\x37\x49\x9e\x04\xb0\x36\xe9" +xa+="\x7f\x44\x5a\x95\x6f\x63\x69\xae\x6e\x63\xfd\x27\xea\xe3\xe3\x47" +xa+="\x85\x54\x47\xd3\xba\xc1\xc6\x0c\x10\xe7\x35\x07\x72\xc6\xc0\xc6" +xa+="\xfb\xf9\xca\x3e\x38\xf0\xe8\x65\x88\x25\xd3\xb2\x0f\x1f\x02\x8f" +xa+="\x35\xe3\x4d\x12\x35\x10\x3d\xf2\x33\x9b\x5b\x09\x9d\x3f\xe3\xe5" +xa+="\x34\x6a\x69\x16\x42\xba\xc5\xb0\xbb\x03\xcd\x5d\x04\xd7\x56\x26" +xa+="\x21\x49\x3f\xf1\xc4\x27\x3b\x6a\x45\xc5\xec\xb0\xb5\xe9\x08\xa0" +xa+="\xf9\xf5\x62\x28\x2e\x85\x3e\xfc\x9a\x7e\xa1\x12\xe9\x47\x4f\xf6" +xa+="\x94\x18\xf7\xc4\x7a\xe9\x66\xd4\x52\x4c\xa1\x70\x1b\x60\xa4\xbe" +xa+="\x15\xc7\x5e\x27\xb4\x05\x80\x64\x68\x15\x6e\x02\xcb\xc5\x8f\xf4" +xa+="\x66\x3c\x96\xac\x0c\x87\x36\x81\x35\xfa\x9b\x0b\xb6\x33\x7a\xe2" +xa+="\x58\x52\x1d\x7d\x60\xc2\xa9\x1b\x4e\xd7\x72\xad\x65\x03\x40\x49" +xa+="\x97\xf6\x79\x9d\xf6\x63\xa8\x99\x9c\xfd\x74\x7f\xa0\x67\xb9\x05" +xa+="\x8a\xb3\x3b\xc1\x45\x94\x36\x6f\x28\xf5\xa2\xd9\x00\xb6\x46\x7a" + +# Z +read -d '' shared <<"EOF" +0fdbd9a2 ebf50cba 489b4e4d 7cd6924a 42ee6324 a26988b2 22bc38e6 9cc445f1 +eb47c1a4 62eca39f 39bcd7b8 19dede51 30bc38da ec99c16f 40a4e5c1 9c97b796 +8b41823d a0650e37 13c73e6f 5f2a9dff 2e67dbf5 40ee66f4 e694c28f ba1d604b +71b57b8a eeb67a35 ba425a38 490b6fb9 f713db22 6f893b7a 8962f426 ba3046fb +cff8538c 16f583e8 ae947672 0ba55ff9 75b440d0 c4565cc7 5837d23a fea61a39 +e0b7f6c4 e24c2154 7eb19fce f8dbed10 b06a9cce 971c0f0f ba7c1d5c b5035eaa +4fddd3ba fe757339 e3321e3e 4ebfe9e7 9c6c0401 4df63cf9 28d0a2c0 5b2d5521 +030c35f1 c84c97fe 64cad509 8012a003 d52d24c4 1a1f9348 b7575251 3facb02f +EOF + +# OI +otherinfo="\xa1\xb2\xc3\xd4\xe5\x43\x41\x56\x53\x69\x64\x0d\x64\xc1\xb2" +otherinfo+="\x33\x61\xb2\x61\xde\x78\x68\x8e\xa8\x65\xfc\xff\x11\x3c\x84" + +# DKM +read -d '' derived <<"EOF" +8284e313 02c8a26b 393ec52d 9f9e0882 +EOF + +pcreate_key "-e $prime" user dh:prime @s +expect_keyid primeid + +pcreate_key "-e $xa" user dh:xa @s +expect_keyid xaid + +pcreate_key "-e $private" user dh:private @s +expect_keyid privateid + +marker "COMPUTE DH SHARED SECRET" +dh_compute $privateid $primeid $xaid +expect_multiline payload "$shared" + +marker "COMPUTE DERIVED KEY FROM DH SHARED SECRET (SHA-256)" +echo -e -n $otherinfo | dh_compute_kdf_oi $privateid $primeid $xaid 16 "sha256" +expect_multiline payload "$derived" + +pcreate_key "-e \x01" user dh:leadingzero @s +expect_keyid lzid + +read -d '' derived2 <<"EOF" +0066207b cdab1d64 bbf489b3 d6a0dadc +EOF + +marker "COMPUTE DERIVED KEY WITH LEADING ZEROS" +echo -e -n $otherinfo | dh_compute_kdf_oi $privateid $primeid $lzid 16 "sha256" +expect_multiline payload "$derived2" + +# SHA-224 + +# XephemCAVS +private="\x86\x1b\xa2\x59\xab\xa6\xaa\x57\x7d\xe2\x2f\x50\x8e\xcb\xbc\x26" +private+="\xc5\xac\xfc\xcb\x9e\xa2\x3b\x43\x4d\x6d\x2b\x79" + +# P +prime="\xa5\xb1\x76\x4e\x13\xc8\x16\x99\xab\xa3\x8f\x0d\xc0\xd1\x5e\x15" +prime+="\xf5\x0f\xcd\x5c\xf7\xc2\x23\x72\xca\xfc\x5e\xd7\x62\x94\x1b\xd9" +prime+="\xe0\xfb\x9a\xab\xee\x74\x66\xd2\xc8\x29\xaa\xb0\x31\xdb\x7b\x1b" +prime+="\x5a\x64\xe6\x8e\xd5\x3b\xaf\xb2\x83\xba\x0f\x01\x8b\xeb\x3e\xdc" +prime+="\x95\x7f\xe4\x53\xbe\x0d\xaa\xb6\x1b\x32\x28\x76\x3e\x80\x75\x8c" +prime+="\x6d\x8c\x28\x3c\xf6\x30\xed\xd9\xd7\x0a\x8a\xf3\x30\xdd\x0a\xf6" +prime+="\xa8\xd5\x94\xc2\x3c\xdd\x24\xc8\xad\x3f\xcf\xea\x41\x75\x77\x72" +prime+="\xce\xed\x92\x1e\x63\x86\x2f\x24\x6e\x6f\x49\xd8\x74\x7e\x44\xae" +prime+="\xf0\x1e\x30\x9b\x6d\xcc\x80\xd4\x50\x38\x3b\xb1\xf9\x4d\xd5\x90" +prime+="\x84\xf8\xe9\x6f\x85\x6e\xc7\xc8\x33\x5e\xdb\x05\x5f\x8e\xc6\xc4" +prime+="\x81\x52\x0b\x3f\x28\xe8\x0b\x62\x09\xb8\xae\x61\xcc\x86\x0e\x24" +prime+="\xc8\x22\xb6\x6c\x4f\x97\x80\x49\x93\xbc\xd0\xa9\x72\xb3\x53\x54" +prime+="\x01\x33\x0e\xbe\x4b\x2e\x92\x3f\x18\x9b\x63\x35\x62\xe4\x68\xeb" +prime+="\x99\xa4\xbc\x88\xcc\xbf\xf8\xdf\x0f\xd5\xaf\xcf\xe6\xae\x19\x18" +prime+="\x42\x14\xab\x3f\xef\xb7\xf0\x66\x8b\x8b\x26\x83\xbe\xbd\x56\x51" +prime+="\xa4\xc6\x38\x43\xb9\xb1\x4b\xc7\x38\xd5\x20\xb1\xb7\x21\x2c\x69" + +# YephemIUT +xa="\x17\xd7\x1a\xf4\x35\x3c\x22\x12\x2a\xeb\x2a\x06\x19\xcc\x2c\xf7" +xa+="\x35\x53\xf2\x8e\x9f\xb1\x91\xfd\xb2\x86\xb1\x15\xb9\xfd\xa8\x66" +xa+="\x2d\xe5\x17\x3b\x1a\xff\x70\x48\x8d\x9b\xc8\x48\xe5\x37\xd7\xe5" +xa+="\x02\x16\x49\xd3\x7d\xc7\x8c\x94\x36\x9d\xb9\x0c\x27\x84\xc9\x4d" +xa+="\x97\x0a\xc9\xb5\xe3\x5e\xfd\x22\xd4\x18\xd3\x1b\x68\xd9\x55\x0b" +xa+="\xaa\x77\x16\xe9\x8e\xa6\x78\x3b\xb3\xa8\x45\x05\x9f\xba\xa4\xa6" +xa+="\x72\x0a\x6a\x23\xc5\x6b\xa5\x2b\x4d\x9b\x72\x6e\x00\x68\xe9\xeb" +xa+="\x4d\x17\x5b\xff\x43\x69\xf3\xd2\xa4\xaf\x66\xee\xcd\x62\xef\x7b" +xa+="\x23\xc3\x37\xd4\x70\x95\x2b\x17\x67\xc8\xbf\x78\x2f\x0b\x58\xb4" +xa+="\xfc\x82\x45\xf8\x40\x78\x71\x70\xf4\xb0\xa5\x1b\x5e\xb4\x60\x75" +xa+="\x8a\xdd\xc9\xf4\x4a\x73\xa3\xf6\x07\x60\x3b\xd3\x50\x73\xd1\xa6" +xa+="\x9a\x20\x3a\x04\x94\xa8\xc2\x02\x1b\xa0\xda\x1f\x04\x95\xf5\x60" +xa+="\xc0\xba\x81\x79\x4e\xee\xeb\x82\x5d\x1b\xd3\x43\x16\xa5\x2a\xe1" +xa+="\xc9\x00\x10\x0c\x0d\x6f\xa0\x25\x46\xed\x7a\x9c\x38\xa6\xa3\x43" +xa+="\xd6\x86\x59\xee\xb5\x9c\xf3\x81\x04\xa9\x6b\xb2\x5a\x6d\xbb\xf0" +xa+="\xcb\xc0\xed\xe7\x3a\x7b\xba\x67\x51\x81\xe0\xcd\x2e\x7b\x9f\x89" + +# Z +read -d '' shared <<"EOF" +057c22b8 c5872fef 08ebe852 fafab4b7 c2c2ffbb 376d71bd a941b16e 32614adf +ebb82aeb d50f29d3 cec63d10 77f50e21 cf381b87 a818c614 52c5cce2 af85f40c +06615b97 fe8c3a80 68990ac5 83957b52 8dd6d52d a3b51e84 aec355fd 4a3fe5ce +faa3b17c 9e71cb4d 28ecab6d 21297280 e52397b7 ccb1b62d 8d5d3ce4 1d26b2a3 +bdbf880b b39e8b02 8a745ff2 9f0984da efe97084 5d850884 525403ca d2a52956 +f55b9a89 b2d801f1 710333c0 479c5955 b54c8163 83c65ad9 c78b8c67 cc1b211b +208b9fab b9c99a68 18293e6a 8da069e6 75eb4317 668a7d4b 6f235533 f3ff4ed0 +4f8ad579 f9ad14e7 f68ae183 41d603d9 d6297123 00716c98 bbbf16eb 2a2cc92f +EOF + +# OI +otherinfo="\xa1\xb2\xc3\xd4\xe5\x43\x41\x56\x53\x69\x64\xaa\x27\xe2\x49" +otherinfo+="\xbf\x0a\x12\x76\x46\x8d\x80\x82\x59\xf3\xb8\xe2\x68\x78\x51" + +# DKM +read -d '' derived <<"EOF" +88bf39c0 08eec33a dc3b4430 054ba262 +EOF + +pcreate_key "-e $prime" user dh:prime @s +expect_keyid primeid + +pcreate_key "-e $xa" user dh:xa @s +expect_keyid xaid + +pcreate_key "-e $private" user dh:private @s +expect_keyid privateid + +marker "COMPUTE DH SHARED SECRET" +dh_compute $privateid $primeid $xaid +expect_multiline payload "$shared" + +marker "COMPUTE DERIVED KEY FROM DH SHARED SECRET (SHA-224)" +echo -e -n $otherinfo | dh_compute_kdf_oi $privateid $primeid $xaid 16 "sha224" +expect_multiline payload "$derived" + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/instantiating/bad-args/runtest.sh b/tests/keyctl/instantiating/bad-args/runtest.sh new file mode 100644 index 0000000000..192228242d --- /dev/null +++ b/tests/keyctl/instantiating/bad-args/runtest.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +instantiate_key --fail 0 a @p +expect_error EPERM +pinstantiate_key --fail a 0 @p +expect_error EPERM +negate_key --fail 0 10 @p +expect_error EPERM + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# check that instantiation of an instantiated key fails +marker "CHECK ALREADY INSTANTIATED KEY" +instantiate_key --fail $keyid a @p +expect_error EPERM +pinstantiate_key --fail a $keyid @p +expect_error EPERM +negate_key --fail $keyid 10 @p +expect_error EPERM + +# check negative key timeout must be a number +marker "CHECK NEGATE TIMEOUT" +expect_args_error keyctl negate $keyid aa @p + +# dispose of the key we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK NON-EXISTENT KEY ID" +instantiate_key --fail 0 a @p +expect_error EPERM +pinstantiate_key --fail a 0 @p +expect_error EPERM +negate_key --fail 0 10 @p +expect_error EPERM + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/instantiating/noargs/runtest.sh b/tests/keyctl/instantiating/noargs/runtest.sh new file mode 100644 index 0000000000..1b5150ff32 --- /dev/null +++ b/tests/keyctl/instantiating/noargs/runtest.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl instantiate +expect_args_error keyctl pinstantiate +expect_args_error keyctl negate + +marker "ONE ARG" +expect_args_error keyctl instantiate 0 +expect_args_error keyctl pinstantiate 0 +expect_args_error keyctl negate 0 + +marker "TWO ARGS" +expect_args_error keyctl instantiate 0 0 +expect_args_error keyctl negate 0 0 + +marker "THREE ARGS" +expect_args_error keyctl pinstantiate 0 0 0 + +marker "FOUR ARGS" +expect_args_error keyctl instantiate 0 0 0 0 +expect_args_error keyctl negate 0 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/invalidate/bad-args/runtest.sh b/tests/keyctl/invalidate/bad-args/runtest.sh new file mode 100644 index 0000000000..2d9ab110e8 --- /dev/null +++ b/tests/keyctl/invalidate/bad-args/runtest.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_key_invalidate = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF KEY INVALIDATION" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK INVALIDATE BAD KEY ID" +invalidate_key --fail 0 +expect_error EINVAL + +# create a key +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# and dispose of it +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK INVALIDATE NON-EXISTENT KEY ID" +invalidate_key --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/invalidate/noargs/runtest.sh b/tests/keyctl/invalidate/noargs/runtest.sh new file mode 100644 index 0000000000..25b19bafbf --- /dev/null +++ b/tests/keyctl/invalidate/noargs/runtest.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_key_invalidate = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF KEY INVALIDATION" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl invalidate + +# check that two arguments fail correctly +marker "TWO ARGS" +expect_args_error keyctl invalidate 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/invalidate/valid/runtest.sh b/tests/keyctl/invalidate/valid/runtest.sh new file mode 100644 index 0000000000..afc0d3ec8f --- /dev/null +++ b/tests/keyctl/invalidate/valid/runtest.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +if [ $have_key_invalidate = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF KEY INVALIDATION" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# check that we have an empty keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING 2" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# invalidate the key +marker "INVALIDATE KEY" +invalidate_key $keyid + +# need to wait for the gc +sleep 1 + +# check that it's now empty again +marker "LIST KEYRING 3" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick another key in the keyring +marker "ADD KEY" +create_key user lizard2 gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING 4" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# invalidate the keyring +marker "INVALIDATE KEYRING" +invalidate_key $keyringid + +# need to wait for the gc +sleep 1 + +# check that the keyring no longer exists +marker "CHECK KEYRING" +list_keyring --fail $keyringid +expect_error ENOKEY + +# check that the key got gc'd also +marker "CHECK KEY" +describe_key --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/link/bad-args/runtest.sh b/tests/keyctl/link/bad-args/runtest.sh new file mode 100644 index 0000000000..39612f4efb --- /dev/null +++ b/tests/keyctl/link/bad-args/runtest.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK LINK FROM BAD KEY ID" +link_key --fail 0 @s +expect_error EINVAL + +marker "CHECK LINK TO BAD KEY ID" +link_key --fail @s 0 +expect_error EINVAL + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# check that linking to a non-keyring ID fails correctly +marker "CHECK LINK TO NON-KEYRING KEY" +link_key --fail @s $keyid +expect_error ENOTDIR + +# dispose of the key we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK LINK TO NON-EXISTENT KEY ID" +link_key --fail @s $keyid +expect_error ENOKEY + +marker "CHECK LINK FROM NON-EXISTENT KEY ID" +link_key --fail $keyid @s +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/link/noargs/runtest.sh b/tests/keyctl/link/noargs/runtest.sh new file mode 100644 index 0000000000..94c2a9fd79 --- /dev/null +++ b/tests/keyctl/link/noargs/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl link + +# check that one argument fails correctly +marker "ONE ARGS" +expect_args_error keyctl link 0 + +# check that three arguments fails correctly +marker "THREE ARGS" +expect_args_error keyctl link 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/link/recursion/runtest.sh b/tests/keyctl/link/recursion/runtest.sh new file mode 100644 index 0000000000..1012871e09 --- /dev/null +++ b/tests/keyctl/link/recursion/runtest.sh @@ -0,0 +1,185 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "CREATE KEYRING 1" +create_keyring "first" @s +expect_keyid keyringid +set_key_perm $keyringid 0x3f3f0000 + +# attempt to link a keyring to itself +marker "RECURSE 1" +link_key --fail $keyringid $keyringid +expect_error EDEADLK + +# create a second keyring in the first +marker "CREATE KEYRING 2" +create_keyring "second" $keyringid +expect_keyid keyring2id +set_key_perm $keyring2id 0x3f3f0000 + +# attempt to link a keyring to its child keyring +marker "RECURSE 2" +link_key --fail $keyringid $keyring2id +expect_error EDEADLK + +# create a third keyring in the second +marker "CREATE KEYRING 3" +create_keyring "third" $keyring2id +expect_keyid keyring3id +set_key_perm $keyring3id 0x3f3f0000 + +# attempt to link a keyring to its grandchild keyring +marker "RECURSE 3" +link_key --fail $keyringid $keyring3id +expect_error EDEADLK + +# create a fourth keyring in the third +marker "CREATE KEYRING 4" +create_keyring "fourth" $keyring3id +expect_keyid keyring4id +set_key_perm $keyring4id 0x3f3f0000 + +# attempt to link a keyring to its great grandchild keyring +marker "RECURSE 4" +link_key --fail $keyringid $keyring4id +expect_error EDEADLK + +# create a fifth keyring in the fourth +marker "CREATE KEYRING 5" +create_keyring "fifth" $keyring4id +expect_keyid keyring5id +set_key_perm $keyring5id 0x3f3f0000 + +# attempt to link a keyring to its great great grandchild keyring +marker "RECURSE 5" +link_key --fail $keyringid $keyring5id +expect_error EDEADLK + +# create a sixth keyring in the fifth +marker "CREATE KEYRING 6" +create_keyring "sixth" $keyring5id +expect_keyid keyring6id +set_key_perm $keyring6id 0x3f3f0000 + +# attempt to link a keyring to its great great great grandchild keyring +marker "RECURSE 6" +link_key --fail $keyringid $keyring6id +expect_error EDEADLK + +# create a seventh keyring in the sixth +marker "CREATE KEYRING 7" +create_keyring "seventh" $keyring6id +expect_keyid keyring7id +set_key_perm $keyring7id 0x3f3f0000 + +# attempt to link a keyring to its great great great great grandchild keyring +marker "RECURSE 7" +link_key --fail $keyringid $keyring7id +expect_error EDEADLK + +# create an eigth keyring in the seventh +marker "CREATE KEYRING 8" +create_keyring "eighth" @s +expect_keyid keyring8id +set_key_perm $keyring8id 0x3f3f0000 +link_key $keyring8id $keyring7id +unlink_key $keyring8id @s + +# attempt to link a keyring to its great great great great great grandchild keyring +marker "RECURSE 8" +link_key --fail $keyringid $keyring8id +expect_error EDEADLK + +# create a ninth keyring in the eighth +marker "CREATE KEYRING 9" +create_keyring "ninth" @s +expect_keyid keyring9id +set_key_perm $keyring9id 0x3f3f0000 +link_key $keyring9id $keyring8id +unlink_key $keyring9id @s + +# attempt to link a keyring to its great great great great great great grandchild keyring +marker "RECURSE 9" +link_key --fail $keyringid $keyring9id +expect_error ELOOP + +# remove the first keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +# create two stacks of keyrings +marker "CREATE KEYRING STACKS" +create_keyring "A1" @s +expect_keyid aroot +create_keyring "B1" @s +expect_keyid broot +a=$aroot +b=$broot + +for ((i=2; i<=4; i++)) + do + create_keyring "A$i" $a + expect_keyid a + create_keyring "B$i" $b + expect_keyid b +done + +# make sure we can't create a cycle by linking the two stacks together +marker "LINK A TO B" +link_key $aroot $b + +marker "LINK B TO A" +link_key --fail $broot $a +expect_error EDEADLK + +marker "UNLINK A FROM B" +unlink_key $aroot $b + +marker "LINK B TO A" +link_key $broot $a + +marker "LINK A TO B" +link_key --fail $aroot $b +expect_error EDEADLK + +marker "UNLINK B FROM A" +unlink_key $broot $a + +# extend the stacks +marker "EXTEND STACKS" +create_keyring "A5" $a +expect_keyid a +create_keyring "B5" $b +expect_keyid b + +# make sure we can't hide a cycle by linking the two bigger stacks together +marker "CHECK MAXDEPTH A TO B" +link_key $aroot $b +link_key --fail $broot $a +expect_error ELOOP +unlink_key $aroot $b + +marker "CHECK MAXDEPTH B TO A" +link_key $broot $a +link_key --fail $aroot $b +expect_error ELOOP +unlink_key $broot $a + +# remove the two stacks +marker "UNLINK STACKS" +unlink_key $aroot @s +unlink_key $broot @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/link/valid/runtest.sh b/tests/keyctl/link/valid/runtest.sh new file mode 100644 index 0000000000..fc7f28a63d --- /dev/null +++ b/tests/keyctl/link/valid/runtest.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# validate the new keyring's name and type +marker "VALIDATE KEYRING" +describe_key $keyringid +expect_key_rdesc rdesc 'keyring@.*@wibble' + +# check that we can list it +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# link the key across to the session keyring +marker "LINK KEY 1" +link_key $keyid @s + +marker "CHECK KEY LINKAGE" +list_keyring @s +expect_keyring_rlist srlist $keyid + +# link the key across to the session keyring again and again +marker "LINK KEY 2" +link_key $keyid @s + +marker "LINK KEY 3" +link_key $keyid @s + +# subsequent links should displace earlier links, giving us a maximum of 1 link +marker "COUNT LINKS" +list_keyring @s +expect_keyring_rlist srlist + +nlinks=0 +for i in $srlist + do + if [ "x$i" = "x$keyid" ] + then + nlinks=$(($nlinks + 1)) + fi +done + +if [ $nlinks != 1 ] +then + failed +fi + +# remove the links +marker "UNLINK KEY FROM SESSION" +unlink_key $keyid @s + +# removing again should fail +unlink_key --fail $keyid @s +expect_error ENOENT + +# remove that key from the keyring (the key should be destroyed) +marker "UNLINK KEY FROM KEYRING" +unlink_key --wait $keyid $keyringid + +# and a second time should fail, but now the key doesn't exist +unlink_key --fail $keyid $keyringid +expect_error ENOKEY + +# create a second keyring in the first +create_keyring "zebra" $keyringid +expect_keyid keyring2id + +# link thrice across to the session keyring +marker "LINK 2ND KEYRING TO SESSION" +link_key $keyring2id @s +link_key $keyring2id @s +link_key $keyring2id @s + +# subsequent links should displace earlier links, giving us a maximum of 1 link +marker "COUNT KEYRING LINKS" +list_keyring @s +expect_keyring_rlist srlist + +nlinks=0 +for i in $srlist + do + if [ "x$i" = "x$keyring2id" ] + then + nlinks=$(($nlinks + 1)) + fi +done + +if [ $nlinks != 1 ] +then + failed +fi + +# remove the keyring links +marker "UNLINK 2ND KEYRING FROM SESSION" +unlink_key $keyring2id @s + +# removing again should fail +unlink_key --fail $keyring2id @s +expect_error ENOENT + +# make another keyring link +marker "LINK 2ND KEYRING TO SESSION" +link_key $keyring2id @s + +# remove the first keyring we added +marker "UNLINK KEYRING" +unlink_key --wait $keyringid @s + +# remove the second keyring we added +marker "UNLINK 2ND KEYRING" +unlink_key --wait $keyring2id @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/listing/bad-args/runtest.sh b/tests/keyctl/listing/bad-args/runtest.sh new file mode 100644 index 0000000000..beb6c99a9b --- /dev/null +++ b/tests/keyctl/listing/bad-args/runtest.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +list_keyring --fail 0 +expect_error ENOKEY +pretty_list_keyring --fail 0 +expect_error ENOKEY + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# dispose of the key we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK NON-EXISTENT KEY ID" +list_keyring --fail $keyid +expect_error ENOKEY +pretty_list_keyring --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/listing/noargs/runtest.sh b/tests/keyctl/listing/noargs/runtest.sh new file mode 100644 index 0000000000..2d9da99f37 --- /dev/null +++ b/tests/keyctl/listing/noargs/runtest.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl list +expect_args_error keyctl rlist + +marker "TWO ARGS" +expect_args_error keyctl list 0 0 +expect_args_error keyctl rlist 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/listing/valid/runtest.sh b/tests/keyctl/listing/valid/runtest.sh new file mode 100644 index 0000000000..fe67bd48f9 --- /dev/null +++ b/tests/keyctl/listing/valid/runtest.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# validate the new keyring's name and type +marker "VALIDATE KEYRING" +describe_key $keyringid +expect_key_rdesc rdesc 'keyring@.*@wibble' + +# check that we have an empty keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +marker "PRETTY LIST KEYRING" +pretty_list_keyring $keyringid +expect_payload payload "keyring is empty" + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# check that we can pretty list it +marker "PRETTY LIST KEYRING WITH ONE" +pretty_list_keyring $keyringid +expect_payload payload + +if ! expr "$payload" : " *$keyid:.*user: lizard" >&/dev/null +then + failed +fi + +# stick a second key in the keyring +marker "ADD KEY 2" +create_key user snake skin $keyringid +expect_keyid keyid2 + +# check that we can see both keys +marker "LIST KEYRING WITH TWO" +list_keyring $keyringid +expect_keyring_rlist rlist + +if [ "x$rlist" != "x$keyid $keyid2" ] +then + failed +fi + +# check that we can see both keys prettily +marker "PRETTY LIST KEYRING WITH TWO" +pretty_list_keyring $keyringid +prlist="" +for i in `tail -2 $OUTPUTFILE | cut -d: -f1 | sed -e 's@ +@@g'` + do + prlist="$prlist $i" +done + +if [ "x$prlist" != "x $keyid $keyid2" ] +then + failed +fi + +# turn off read permission on the keyring +marker "DISABLE READ PERM" +set_key_perm $keyringid 0x3d0000 +list_keyring $keyringid + +# turn off read and search permission on the keyring +marker "DISABLE SEARCH PERM" +set_key_perm $keyringid 0x350000 +list_keyring --fail $keyringid +expect_error EACCES + +# turn on read permission on the keyring +marker "REINSTATE READ PERM" +set_key_perm $keyringid 0x370000 +list_keyring $keyringid + +# revoke the keyring +marker "REVOKE KEYRING" +revoke_key $keyringid +list_keyring --fail $keyringid +expect_error EKEYREVOKED + +# remove the keyring we added +marker "UNLINK KEY" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/move/bad-args/runtest.sh b/tests/keyctl/move/bad-args/runtest.sh new file mode 100644 index 0000000000..8ce62ffb0e --- /dev/null +++ b/tests/keyctl/move/bad-args/runtest.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK MOVE OF BAD KEY ID" +move_key --fail 0 @u @s +expect_error EINVAL + +marker "CHECK MOVE FROM BAD KEYRING ID" +move_key --fail @u 0 @s +expect_error EINVAL + +marker "CHECK MOVE TO BAD KEYRING ID" +move_key --fail @u @s 0 +expect_error EINVAL + +marker "CHECK FORCED MOVE OF BAD KEY ID" +move_key --fail -f 0 @u @s +expect_error EINVAL + +marker "CHECK FORCED MOVE FROM BAD KEYRING ID" +move_key --fail -f @u 0 @s +expect_error EINVAL + +marker "CHECK FORCED MOVE TO BAD KEYRING ID" +move_key --fail -f @u @s 0 +expect_error EINVAL + +# create a pair of non-keyrings +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +marker "CREATE KEY2" +create_key user zebra stripes @s +expect_keyid keyid2 + +# check that linking to a non-keyring ID fails correctly +marker "CHECK MOVE FROM NON-KEYRING KEY" +move_key --fail $keyid $keyid2 @s +expect_error ENOTDIR + +marker "CHECK MOVE TO NON-KEYRING KEY" +move_key --fail $keyid @s $keyid2 +expect_error ENOTDIR + +# dispose of the keys we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s +marker "UNLINK KEY2" +unlink_key --wait $keyid2 @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/move/noargs/runtest.sh b/tests/keyctl/move/noargs/runtest.sh new file mode 100644 index 0000000000..29a91f1715 --- /dev/null +++ b/tests/keyctl/move/noargs/runtest.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl move +marker "NO ARGS (F)" +expect_args_error keyctl move -f + +# check that one argument fails correctly +marker "ONE ARGS" +expect_args_error keyctl move 0 +marker "ONE ARGS (F)" +expect_args_error keyctl move -f 0 + +# check that two arguments fails correctly +marker "TWO ARGS" +expect_args_error keyctl move 0 0 +marker "TWO ARGS (F)" +expect_args_error keyctl move -f 0 0 + +# check that four arguments fails correctly +marker "FOUR ARGS" +expect_args_error keyctl link 0 0 0 0 +marker "FOUR ARGS (F)" +expect_args_error keyctl link -f 0 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/move/recursion/runtest.sh b/tests/keyctl/move/recursion/runtest.sh new file mode 100644 index 0000000000..1e68963578 --- /dev/null +++ b/tests/keyctl/move/recursion/runtest.sh @@ -0,0 +1,213 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "CREATE KEYRING 1" +create_keyring "first" @s +expect_keyid keyringid +set_key_perm $keyringid 0x3f3f0000 + +# attempt to move a keyring to itself +marker "RECURSE 1" +move_key --fail $keyringid @s $keyringid +expect_error EDEADLK +marker "RECURSE 1F" +move_key --fail -f $keyringid @s $keyringid +expect_error EDEADLK + +# create a second keyring in the first +marker "CREATE KEYRING 2" +create_keyring "second" $keyringid +expect_keyid keyring2id +set_key_perm $keyring2id 0x3f3f0000 + +# attempt to move a keyring to its child keyring +marker "RECURSE 2" +move_key --fail $keyringid @s $keyring2id +expect_error EDEADLK +marker "RECURSE 2F" +move_key --fail -f $keyringid @s $keyring2id +expect_error EDEADLK + +# create a third keyring in the second +marker "CREATE KEYRING 3" +create_keyring "third" $keyring2id +expect_keyid keyring3id +set_key_perm $keyring3id 0x3f3f0000 + +# attempt to move a keyring to its grandchild keyring +marker "RECURSE 3" +move_key --fail $keyringid @s $keyring3id +expect_error EDEADLK +marker "RECURSE 3F" +move_key --fail -f $keyringid @s $keyring3id +expect_error EDEADLK + +# create a fourth keyring in the third +marker "CREATE KEYRING 4" +create_keyring "fourth" $keyring3id +expect_keyid keyring4id +set_key_perm $keyring4id 0x3f3f0000 + +# attempt to move a keyring to its great grandchild keyring +marker "RECURSE 4" +move_key --fail $keyringid @s $keyring4id +expect_error EDEADLK +marker "RECURSE 4F" +move_key --fail -f $keyringid @s $keyring4id +expect_error EDEADLK + +# create a fifth keyring in the fourth +marker "CREATE KEYRING 5" +create_keyring "fifth" $keyring4id +expect_keyid keyring5id +set_key_perm $keyring5id 0x3f3f0000 + +# attempt to move a keyring to its great great grandchild keyring +marker "RECURSE 5" +move_key --fail $keyringid @s $keyring5id +expect_error EDEADLK +marker "RECURSE 5F" +move_key --fail -f $keyringid @s $keyring5id +expect_error EDEADLK + +# create a sixth keyring in the fifth +marker "CREATE KEYRING 6" +create_keyring "sixth" $keyring5id +expect_keyid keyring6id +set_key_perm $keyring6id 0x3f3f0000 + +# attempt to move a keyring to its great great great grandchild keyring +marker "RECURSE 6" +move_key --fail $keyringid @s $keyring6id +expect_error EDEADLK +marker "RECURSE 6F" +move_key --fail -f $keyringid @s $keyring6id +expect_error EDEADLK + +# create a seventh keyring in the sixth +marker "CREATE KEYRING 7" +create_keyring "seventh" $keyring6id +expect_keyid keyring7id +set_key_perm $keyring7id 0x3f3f0000 + +# attempt to move a keyring to its great great great great grandchild keyring +marker "RECURSE 7" +move_key --fail $keyringid @s $keyring7id +expect_error EDEADLK +marker "RECURSE 7F" +move_key --fail -f $keyringid @s $keyring7id +expect_error EDEADLK + +# create an eigth keyring in the seventh +marker "CREATE KEYRING 8" +create_keyring "eighth" @s +expect_keyid keyring8id +set_key_perm $keyring8id 0x3f3f0000 +move_key $keyring8id @s $keyring7id + +# attempt to move a keyring to its great great great great great grandchild keyring +marker "RECURSE 8" +move_key --fail $keyringid @s $keyring8id +expect_error EDEADLK + +# create a ninth keyring in the eighth +marker "CREATE KEYRING 9" +create_keyring "ninth" @s +expect_keyid keyring9id +set_key_perm $keyring9id 0x3f3f0000 +move_key $keyring9id @s $keyring8id + +# attempt to move a keyring to its great great great great great great grandchild keyring +marker "RECURSE 9" +move_key --fail $keyringid @s $keyring9id +expect_error ELOOP +marker "RECURSE 9F" +move_key --fail -f $keyringid @s $keyring9id +expect_error ELOOP + +# remove the first keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +# create two stacks of keyrings +marker "CREATE KEYRING STACKS" +create_keyring "A1" @s +expect_keyid aroot +create_keyring "B1" @s +expect_keyid broot +a=$aroot +b=$broot + +for ((i=2; i<=4; i++)) + do + create_keyring "A$i" $a + expect_keyid a + create_keyring "B$i" $b + expect_keyid b +done + +# make sure we can't create a cycle by linking the two stacks together +marker "LINK A TO B" +link_key $aroot $b + +marker "MOVE B TO A" +move_key --fail $broot @s $a +expect_error EDEADLK +marker "FORCE MOVE B TO A" +move_key --fail -f $broot @s $a +expect_error EDEADLK + +marker "UNLINK A FROM B" +unlink_key $aroot $b + +marker "LINK B TO A" +link_key $broot $a + +marker "MOVE A TO B" +move_key --fail $aroot @s $b +expect_error EDEADLK +marker "FORCE MOVE A TO B" +move_key --fail -f $aroot @s $b +expect_error EDEADLK + +marker "UNLINK B FROM A" +unlink_key $broot $a + +# extend the stacks +marker "EXTEND STACKS" +create_keyring "A5" $a +expect_keyid a +create_keyring "B5" $b +expect_keyid b + +# make sure we can't hide a cycle by linking the two bigger stacks together +marker "CHECK MAXDEPTH A TO B" +link_key $aroot $b +move_key --fail $broot @s $a +expect_error ELOOP +unlink_key $aroot $b + +marker "CHECK MAXDEPTH B TO A" +link_key $broot $a +move_key --fail $aroot @s $b +expect_error ELOOP +unlink_key $broot $a + +# remove the two stacks +marker "UNLINK STACKS" +unlink_key $aroot @s +unlink_key $broot @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/move/valid/runtest.sh b/tests/keyctl/move/valid/runtest.sh new file mode 100644 index 0000000000..73bf7c2370 --- /dev/null +++ b/tests/keyctl/move/valid/runtest.sh @@ -0,0 +1,230 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# move the key across to the session keyring +marker "MOVE KEY 1" +move_key $keyid $keyringid @s + +marker "CHECK KEY LINKAGE" +list_keyring @s +expect_keyring_rlist srlist $keyid + +marker "CHECK KEY REMOVED" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid --absent + +# Repeating the move should fail +marker "MOVE KEY 2" +move_key --fail $keyid $keyringid @s +expect_error ENOENT + +marker "FORCE MOVE KEY 2" +move_key --fail -f $keyid $keyringid @s +expect_error ENOENT + +# Move the key back again +marker "MOVE KEY 3" +move_key $keyid @s $keyringid + +marker "MOVE KEY 4" +move_key --fail -f $keyid @s $keyringid +expect_error ENOENT + +# Create a conflicting key and try to have an unforced move displace it +marker "ADD KEY 2" +create_key user lizard gizzard @s +expect_keyid keyid2 + +marker "MOVE KEY 5" +move_key --fail $keyid $keyringid @s +expect_error EEXIST + +marker "CHECK KEY UNMOVED" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +marker "CHECK KEY UNDISPLACED" +list_keyring @s +expect_keyring_rlist srlist $keyid --absent +expect_keyring_rlist srlist $keyid2 + +# Now try a forced move +marker "FORCE MOVE KEY 6" +move_key -f $keyid $keyringid @s + +marker "CHECK KEY REMOVED" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid --absent +expect_keyring_rlist rlist $keyid2 --absent + +marker "CHECK KEY DISPLACED" +list_keyring @s +expect_keyring_rlist srlist $keyid +expect_keyring_rlist srlist $keyid2 --absent + +# Remove the link (the key should be destroyed) +marker "UNLINK KEY FROM SESSION" +unlink_key --wait $keyid @s + +# Removing again should fail +unlink_key --fail $keyid @s +expect_error ENOKEY + +# Remove that key from the keyring should also fail +marker "UNLINK KEY FROM KEYRING" +unlink_key --fail $keyid $keyringid +expect_error ENOKEY + +############################################################################### +# Create a second keyring in the first +create_keyring "zebra" $keyringid +expect_keyid keyring2id + +# Move thrice between the session keyring and back +marker "LINK 2ND KEYRING TO SESSION" +move_key $keyring2id $keyringid @s +move_key $keyring2id @s $keyringid +move_key $keyring2id $keyringid @s + +# Subsequent links should displace earlier links, giving us a maximum of 1 link +marker "COUNT KEYRING LINKS" +list_keyring @s +expect_keyring_rlist srlist + +nlinks=0 +for i in $srlist + do + if [ "x$i" = "x$keyring2id" ] + then + nlinks=$(($nlinks + 1)) + fi +done + +if [ $nlinks != 1 ] +then + failed +fi + +# Remove the keyring links, destroying it +marker "UNLINK 2ND KEYRING FROM SESSION" +unlink_key --wait $keyring2id @s + +# Removing again should fail +marker "RE-UNLINK" +unlink_key --fail $keyring2id @s +expect_error ENOKEY +marker "RE-UNLINK 2" +unlink_key --fail $keyring2id $keyringid +expect_error ENOKEY + +############################################################################### +# Create a second keyring in the session keyring +create_keyring "zebra" @s +expect_keyid keyring2id + +# Add a key to the session keyring and link it into each keyring +marker "ADD KEY 3" +create_key user lizard gizzard @s +expect_keyid keyid + +marker "LINK KEY" +link_key $keyid $keyringid +marker "LINK KEY 2" +link_key $keyid $keyring2id + +# Try to move the links from the keyrings into the session keyring +marker "MOVE LINK" +move_key --fail $keyid $keyringid @s +expect_error EEXIST + +marker "CHECK LINK" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +marker "MOVE LINK 2" +move_key --fail $keyid $keyring2id @s +expect_error EEXIST + +marker "CHECK LINK 2" +list_keyring $keyring2id +expect_keyring_rlist rlist $keyid + +marker "MOVE LINK 3" +move_key $keyid @s @s + +marker "CHECK LINK 3" +list_keyring @s +expect_keyring_rlist srlist $keyid + +# Try to force move the links from the keyrings into the session keyring +marker "FORCE MOVE LINK" +move_key -f $keyid $keyringid @s + +marker "CHECK LINK 4" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid --absent + +marker "CHECK LINK 4s" +list_keyring @s +expect_keyring_rlist srlist $keyid + +marker "FORCE MOVE LINK 2" +move_key -f $keyid $keyring2id @s + +marker "CHECK LINK 5" +list_keyring $keyring2id +expect_keyring_rlist rlist $keyid --absent + +marker "CHECK LINK 5s" +list_keyring @s +expect_keyring_rlist srlist $keyid + +marker "FORCE MOVE LINK 3" +move_key -f $keyid @s @s + +marker "CHECK LINK 6" +list_keyring @s +expect_keyring_rlist srlist $keyid + +# Move the key between keyrings +marker "ROTATE" +move_key $keyid @s $keyringid +move_key $keyid $keyringid $keyring2id +move_key $keyid $keyring2id @s + +marker "UNLINK KEY" +unlink_key $keyid @s + +# remove the keyrings +marker "UNLINK KEYRING 1" +unlink_key --wait $keyringid @s +marker "UNLINK KEYRING 2" +unlink_key --wait $keyring2id @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/newring/bad-args/runtest.sh b/tests/keyctl/newring/bad-args/runtest.sh new file mode 100644 index 0000000000..9b0fe018d5 --- /dev/null +++ b/tests/keyctl/newring/bad-args/runtest.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that an max length key description works correctly (4096 inc NUL) +if [ $PAGE_SIZE -lt $maxsquota ] +then + marker "CHECK MAXLEN DESC" + create_keyring $maxdesc @p + expect_keyid keyid +else + marker "CHECK MAXLEN DESC FAILS WITH EDQUOT" + create_keyring --fail $maxdesc @p + expect_error EDQUOT +fi + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong key description fails correctly (>4095 inc NUL) + marker "CHECK OVERLONG DESC" + create_keyring --fail a$maxdesc @p + expect_error EINVAL +fi + +# check that an empty keyring name fails +marker "CHECK EMPTY KEYRING NAME" +create_keyring --fail "" @p +expect_error EINVAL + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +create_keyring --fail wibble 0 +expect_error EINVAL + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/newring/noargs/runtest.sh b/tests/keyctl/newring/noargs/runtest.sh new file mode 100644 index 0000000000..eedef68260 --- /dev/null +++ b/tests/keyctl/newring/noargs/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl newring + +# check that one argument fails correctly +marker "ADD ONE ARG" +expect_args_error keyctl newring user + +# check that three arguments fail correctly +marker "ADD THREE ARGS" +expect_args_error keyctl newring user wibble stuff + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/newring/valid/runtest.sh b/tests/keyctl/newring/valid/runtest.sh new file mode 100644 index 0000000000..b89a0d18e6 --- /dev/null +++ b/tests/keyctl/newring/valid/runtest.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# check that we now have an empty keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# check that creating a second keyring of the same name displaces the first +marker "ADD KEYRING AGAIN" +create_keyring wibble @s +expect_keyid keyringid2 + +# should be different keyrings +if [ "x$keyringid" == "x$keyringid2" ] +then + failed +fi + +# the first should no longer exist in the session keyring +marker "LIST SESSION KEYRING" +list_keyring @s +expect_keyring_rlist sessionrlist $keyringid --absent + +# and should no longer be accessible +marker "VALIDATE NEW KEYRING" +pause_till_key_destroyed $keyringid +describe_key --fail $keyringid +expect_error ENOKEY + +# list the session keyring +marker "LIST SESSION KEYRING2" +list_keyring @s +expect_keyring_rlist sessionrlist $keyringid2 + +# validate the new keyring's name and type +marker "VALIDATE NEW KEYRING2" +describe_key $keyringid2 +expect_key_rdesc rdesc 'keyring@.*@wibble' + +# remove the keyring we added +marker "UNLINK KEY" +unlink_key $keyringid2 @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/noargs/runtest.sh b/tests/keyctl/noargs/runtest.sh new file mode 100644 index 0000000000..c00e3e7c8e --- /dev/null +++ b/tests/keyctl/noargs/runtest.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +. ../../prepare.inc.sh +. ../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "CHECK NO ARGS" +expect_args_error keyctl + +if [ "`sed -n -e 3p $OUTPUTFILE | cut -d: -f1`" != "Format" ] +then + failed +fi + + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/padd/bad-args/runtest.sh b/tests/keyctl/padd/bad-args/runtest.sh new file mode 100644 index 0000000000..fc82682c6d --- /dev/null +++ b/tests/keyctl/padd/bad-args/runtest.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that an empty key type fails correctly +marker "CHECK EMPTY KEY TYPE" +pcreate_key --fail stuff "" wibble @p +expect_error EINVAL + +# check that an unsupported key type fails correctly +marker "CHECK UNSUPPORTED KEY TYPE" +pcreate_key --fail stuff lizardsgizzards wibble @p +expect_error ENODEV + +# check that an invalid key type fails correctly +marker "CHECK INVALID KEY TYPE" +pcreate_key --fail stuff .user wibble @p +expect_error EPERM + +# check that an maximum length invalid key type fails correctly +marker "CHECK MAXLEN KEY TYPE" +pcreate_key --fail stuff $maxtype wibble @p +expect_error ENODEV + +# check that an overlong key type fails correctly +marker "CHECK OVERLONG KEY TYPE" +pcreate_key --fail stuff a$maxtype wibble @p +expect_error EINVAL + +# check that creation of a keyring with non-empty payload fails correctly +marker "CHECK ADD KEYRING WITH PAYLOAD" +pcreate_key --fail stuff keyring wibble @p +expect_error EINVAL + +# check that an max length key description works correctly +if [ $PAGE_SIZE -lt $maxsquota ] +then + marker "CHECK MAXLEN DESC" + pcreate_key stuff user $maxdesc @p + expect_keyid keyid +else + marker "CHECK MAXLEN DESC FAILS WITH EDQUOT" + pcreate_key --fail stuff user $maxdesc @p + expect_error EDQUOT +fi + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong key description fails correctly (>4095 inc NUL) + marker "CHECK OVERLONG DESC" + pcreate_key --fail stuff user a$maxdesc @p + expect_error EINVAL +fi + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +pcreate_key --fail stuff user wibble 0 +expect_error EINVAL + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/padd/noargs/runtest.sh b/tests/keyctl/padd/noargs/runtest.sh new file mode 100644 index 0000000000..5839b071df --- /dev/null +++ b/tests/keyctl/padd/noargs/runtest.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl padd + +# check that one argument fails correctly +marker "ADD ONE ARG" +expect_args_error keyctl padd user + +# check that two arguments fail correctly +marker "ADD TWO ARGS" +expect_args_error keyctl padd user wibble + +# check that four arguments fail correctly +marker "ADD FOUR ARGS" +expect_args_error keyctl padd user wibble @s x + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/padd/useradd/runtest.sh b/tests/keyctl/padd/useradd/runtest.sh new file mode 100644 index 0000000000..206a163f88 --- /dev/null +++ b/tests/keyctl/padd/useradd/runtest.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that we can add a user key to the session keyring +marker "ADD USER KEY" +pcreate_key stuff user wibble @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + +# check that we can update a user key +marker "UPDATE USER KEY" +pcreate_key lizard user wibble @s + +# check we get the same key ID back +expect_keyid keyid2 + +if [ "x$keyid" != "x$keyid2" ] +then + failed +fi + +# read back what we changed it to +marker "PRINT UPDATED PAYLOAD" +print_key $keyid +expect_payload payload "lizard" + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid @s + +if [ $skip_root_required = 0 ] && { + [ $OSDIST = RHEL ] && ! version_less_than $OSRELEASE 6.6 || + keyutils_at_or_later_than 1.5.6 ; + } +then + # add keys with huge payloads + old_root_quota=`cat /proc/sys/kernel/keys/root_maxbytes` + if [ $old_root_quota -lt 65536 ] + then + marker "INCREASE QUOTA" + echo 65536 >/proc/sys/kernel/keys/root_maxbytes + fi + + marker "ADD LARGE USER KEY" + pcreate_key_by_size 32767 user large @s + expect_keyid keyid + md5sum_key $keyid + expect_payload payload "f128f774ede3fe931e7c6745c4292f40" + + if [ $have_big_key_type = 1 ] + then + marker "ADD SMALL BIG KEY" + pcreate_key_by_size 128 big_key small @s + expect_keyid keyid + md5sum_key $keyid + expect_payload payload "f09f35a5637839458e462e6350ecbce4" + + marker "ADD HUGE BIG KEY" + pcreate_key_by_size $((1024*1024-1)) big_key huge @s + expect_keyid keyid + md5sum_key $keyid + expect_payload payload "e57598cd670284cf7d09e16ed9d4b2ac" + fi + + marker "CLEAR KEYRING" + clear_keyring @s + + if [ $old_root_quota -lt 65536 ] + then + marker "RESET QUOTA" + echo $old_root_quota >/proc/sys/kernel/keys/root_maxbytes + sleep 1 + fi +fi + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/permitting/bad-args/runtest.sh b/tests/keyctl/permitting/bad-args/runtest.sh new file mode 100644 index 0000000000..630f85fe57 --- /dev/null +++ b/tests/keyctl/permitting/bad-args/runtest.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +chown_key --fail 0 0 +expect_error EINVAL +chgrp_key --fail 0 0 +expect_error EINVAL +set_key_perm --fail 0 0 +expect_error EINVAL + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# check that unsupported permissions aren't permitted +marker "CHECK PERMS" +set_key_perm --fail $keyid 0xffffffff +expect_error EINVAL +set_key_perm --fail $keyid 0x7f7f7f7f +expect_error EINVAL + +# dispose of the key we just made +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK CLEAR NON-EXISTENT KEY ID" +chown_key --fail $keyid 0 +expect_error ENOKEY +chgrp_key --fail $keyid 0 +expect_error ENOKEY +set_key_perm --fail $keyid 0 +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/permitting/noargs/runtest.sh b/tests/keyctl/permitting/noargs/runtest.sh new file mode 100644 index 0000000000..5a9408fa17 --- /dev/null +++ b/tests/keyctl/permitting/noargs/runtest.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl read +expect_args_error keyctl pipe +expect_args_error keyctl print + +marker "ONE ARG" +expect_args_error keyctl chown 0 +expect_args_error keyctl chgrp 0 +expect_args_error keyctl setperm 0 + +marker "THREE ARGS" +expect_args_error keyctl chown 0 0 0 +expect_args_error keyctl chgrp 0 0 0 +expect_args_error keyctl setperm 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/permitting/valid/runtest.sh b/tests/keyctl/permitting/valid/runtest.sh new file mode 100644 index 0000000000..70600e7002 --- /dev/null +++ b/tests/keyctl/permitting/valid/runtest.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# changing the key's ownership is not supported before 2.6.18-rc1 +if kernel_older_than 2.6.18 +then + marker "CHOWN" + chown_key --fail $keyid 1 + expect_error EOPNOTSUPP +elif [ `id -u` != 0 ] +then + # must be running as root for this to work + marker "CHOWN" + chown_key --fail $keyid 1 + expect_error EACCES +else + marker "CHOWN" + chown_key $keyid 1 + + marker "CHOWN BACK" + chown_key $keyid 0 +fi + +# changing the key's group ownership is supported (change to "bin" group) +if [ `id -u` != 0 ] +then + marker "CHGRP" + chgrp_key --fail $keyid 1 + expect_error EACCES +else + marker "CHGRP" + chgrp_key $keyid 1 + describe_key $keyid + expect_key_rdesc rdesc "user@.*@1@[0-9a-f]*@lizard" +fi + +# check that each permission can be granted to the key +marker "ITERATE PERMISSIONS" +for i in \ + 00210002 00210004 00210008 00210010 \ + 00210200 00210400 00210800 00211000 \ + 00230000 00250000 00290000 00310000 \ + 02210000 04210000 08210000 10210000 + do + set_key_perm $keyid 0x$i + describe_key $keyid + expect_key_rdesc rdesc "user@.*@.*@$i@lizard" +done + +# check that we can't use group perms instead of user perms to view the key +# (our UID matches that of the key) +marker "VIEW GROUP PERMISSIONS" +set_key_perm $keyid 0x00201f00 +describe_key --fail $keyid +expect_error EACCES + +# check that we can't use other perms instead of user perms to view the key +# (our UID matches that of the key) +marker "VIEW OTHER PERMISSIONS" +set_key_perm $keyid 0x0020001f +describe_key --fail $keyid +expect_error EACCES + +# check that taking away setattr permission renders the key immune to setperm +marker "REMOVE SETATTR" +set_key_perm $keyid 0x1f1f1f1f +describe_key $keyid +expect_key_rdesc rdesc "user@.*@.*@.*@lizard" + +marker "REINSTATE SETATTR" +set_key_perm --fail $keyid 0x3f3f1f1f +expect_error EACCES + +# remove the keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/pupdate/bad-args/runtest.sh b/tests/keyctl/pupdate/bad-args/runtest.sh new file mode 100644 index 0000000000..bced352f44 --- /dev/null +++ b/tests/keyctl/pupdate/bad-args/runtest.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# attempt to update the session keyring +marker "CHECK UPDATE SESSION KEYRING" +pupdate_key --fail @s a +expect_error EOPNOTSUPP + +# attempt to update an invalid key +marker "CHECK UPDATE INVALID KEY" +pupdate_key --fail 0 a +expect_error EINVAL + +# add a user key to the session keyring for us to play with +marker "ADD USER KEY" +create_key user wibble stuff @s +expect_keyid keyid + +# remove the key we just added +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# it should fail when we attempt to update it +marker "UPDATE UNLINKED KEY" +pupdate_key --fail $keyid @s +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/pupdate/noargs/runtest.sh b/tests/keyctl/pupdate/noargs/runtest.sh new file mode 100644 index 0000000000..d995851305 --- /dev/null +++ b/tests/keyctl/pupdate/noargs/runtest.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "PUPDATE NO ARGS" +expect_args_error keyctl pupdate + +# check that two arguments fail correctly +marker "PUPDATE TWO ARGS" +expect_args_error keyctl pupdate yyy xxxx + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/pupdate/userupdate/runtest.sh b/tests/keyctl/pupdate/userupdate/runtest.sh new file mode 100644 index 0000000000..05a77c1a6c --- /dev/null +++ b/tests/keyctl/pupdate/userupdate/runtest.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that we can add a user key to the session keyring +marker "ADD USER KEY" +create_key user wibble stuff @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + +# check that we can update a user key +marker "PUPDATE USER KEY" +pupdate_key $keyid "lizard" + +# read back what we changed it to +marker "PRINT UPDATED PAYLOAD" +print_key $keyid +expect_payload payload "lizard" + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/reading/bad-args/runtest.sh b/tests/keyctl/reading/bad-args/runtest.sh new file mode 100644 index 0000000000..35ce9a3233 --- /dev/null +++ b/tests/keyctl/reading/bad-args/runtest.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +read_key --fail 0 +expect_error ENOKEY +print_key --fail 0 +expect_error ENOKEY +pipe_key --fail 0 +expect_error ENOKEY + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# dispose of the key we just made +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK CLEAR NON-EXISTENT KEY ID" +read_key --fail $keyid +expect_error ENOKEY +print_key --fail $keyid +expect_error ENOKEY +pipe_key --fail $keyid +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/reading/noargs/runtest.sh b/tests/keyctl/reading/noargs/runtest.sh new file mode 100644 index 0000000000..4053b652a3 --- /dev/null +++ b/tests/keyctl/reading/noargs/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +marker "NO ARGS" +expect_args_error keyctl read +expect_args_error keyctl pipe +expect_args_error keyctl print + +marker "TWO ARGS" +expect_args_error keyctl read 0 0 +expect_args_error keyctl pipe 0 0 +expect_args_error keyctl print 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/reading/valid/runtest.sh b/tests/keyctl/reading/valid/runtest.sh new file mode 100644 index 0000000000..8e4d864a41 --- /dev/null +++ b/tests/keyctl/reading/valid/runtest.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that the key is in the keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# read the contents of the key +marker "PRINT KEY" +print_key $keyid +expect_payload payload "gizzard" + +# pipe the contents of the key and add a LF as the key doesn't have one +marker "PIPE KEY" +pipe_key $keyid +echo >>$OUTPUTFILE +expect_payload payload "gizzard" + +# read the key as hex +marker "READ KEY" +read_key $keyid +expect_payload payload "67697a7a 617264" + +# read the contents of the keyring as hex and match it to the key ID +marker "READ KEYRING" +read_key $keyringid +tmp=`printf %08x $keyid` +if [ "$endian" = "LE" ] +then + tmp=`echo $tmp | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/'` +fi +expect_payload payload $tmp + +# remove read permission from the key and try reading it again +# - we should still have read permission because it's searchable in our +# keyrings +marker "REMOVE READ PERM" +set_key_perm $keyid 0x3d0000 +print_key $keyid +expect_payload payload "gizzard" + +# remove search permission from the key as well +# - we should still have read permission because it's searchable in our +# keyrings +marker "REMOVE SEARCH PERM" +set_key_perm $keyid 0x350000 +print_key --fail $keyid +expect_error EACCES + +# check that we can read it if we have to rely on possessor perms +# - we should still have read permission because it's searchable in our +# keyrings +marker "CHECK POSSESSOR READ" +set_key_perm $keyid 0x3d000000 +print_key $keyid +expect_payload payload "gizzard" + +# put read permission back again +marker "REINSTATE READ PERM" +set_key_perm $keyid 0x370000 +print_key $keyid +expect_payload payload "gizzard" + +# revoke the key +marker "REVOKE KEY" +revoke_key $keyid +print_key --fail $keyid +expect_error EKEYREVOKED + +# remove the keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/requesting/bad-args/runtest.sh b/tests/keyctl/requesting/bad-args/runtest.sh new file mode 100644 index 0000000000..83c114f584 --- /dev/null +++ b/tests/keyctl/requesting/bad-args/runtest.sh @@ -0,0 +1,128 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +if [ $skip_install_required -eq 1 ] +then + echo "++++ SKIPPING TEST" >$OUTPUTFILE + marker "SKIP BECAUSE TEST REQUIRES FULL INSTALL (for /sbin/request-key)" + toolbox_report_result $TEST PASS + exit 0 +else + echo "++++ BEGINNING TEST" >$OUTPUTFILE +fi + +# check that an empty key type fails correctly +marker "CHECK EMPTY KEY TYPE" +request_key --fail "" debug:wibble +expect_error EINVAL +request_key --fail "" debug:wibble @p +expect_error EINVAL +request_key_callout --fail "" debug:wibble stuff +expect_error EINVAL +request_key_callout --fail "" debug:wibble stuff @p +expect_error EINVAL +prequest_key_callout --fail stuff "" debug:wibble +expect_error EINVAL +prequest_key_callout --fail stuff "" debug:wibble @p +expect_error EINVAL + +# check that an unsupported key type fails correctly +marker "CHECK UNSUPPORTED KEY TYPE" +request_key --fail "lizardsgizzards" debug:wibble +expect_error ENOKEY +request_key --fail "lizardsgizzards" debug:wibble @p +expect_error ENOKEY +request_key_callout --fail "lizardsgizzards" debug:wibble stuff +expect_error ENOKEY +request_key_callout --fail "lizardsgizzards" debug:wibble stuff @p +expect_error ENOKEY +prequest_key_callout --fail stuff "lizardsgizzards" debug:wibble +expect_error ENOKEY +prequest_key_callout --fail stuff "lizardsgizzards" debug:wibble @p +expect_error ENOKEY + +# check that an invalid key type fails correctly +# - key types beginning with a dot are internal use only +marker "CHECK INVALID KEY TYPE" +request_key --fail ".user" debug:wibble +expect_error EPERM +request_key --fail ".user" debug:wibble @p +expect_error EPERM +request_key_callout --fail ".user" debug:wibble stuff +expect_error EPERM +request_key_callout --fail ".user" debug:wibble stuff @p +expect_error EPERM +prequest_key_callout --fail stuff ".user" debug:wibble +expect_error EPERM +prequest_key_callout --fail stuff ".user" debug:wibble @p +expect_error EPERM + +# check that an maximum length invalid key type fails correctly +marker "CHECK MAXLEN INVALID KEY TYPE" +request_key --fail $maxtype debug:wibble +expect_error ENOKEY +request_key --fail $maxtype debug:wibble @p +expect_error ENOKEY +request_key_callout --fail $maxtype debug:wibble stuff +expect_error ENOKEY +request_key_callout --fail $maxtype debug:wibble stuff @p +expect_error ENOKEY + +# check that an overlong key type fails correctly +marker "CHECK OVERLONG KEY TYPE" +request_key --fail a$maxtype debug:wibble +expect_error EINVAL +request_key --fail a$maxtype debug:wibble @p +expect_error EINVAL +request_key_callout --fail a$maxtype debug:wibble stuff +expect_error EINVAL +request_key_callout --fail a$maxtype debug:wibble stuff @p +expect_error EINVAL + +# check that an max length key description works correctly +marker "CHECK MAXLEN DESC" +request_key --fail user $maxdesc +expect_error ENOKEY + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong key description fails correctly + marker "CHECK OVERLONG DESC" + request_key --fail user a$maxdesc + expect_error EINVAL +fi + +# check that a max length callout info works correctly +marker "CHECK MAXLEN CALLOUT" +request_key_callout --fail user wibble $maxdesc @p +expect_error ENOKEY + +# check that an overlong callout info fails correctly +marker "CHECK OVERLONG CALLOUT" +request_key_callout --fail user wibble a$maxcall +expect_error EINVAL + +# check that a max length callout info works correctly +marker "CHECK MAXLEN PIPED CALLOUT" +prequest_key_callout --fail $maxcall user wibble @p +expect_error ENOKEY + +# check that an overlong callout info fails correctly +marker "CHECK OVERLONG PIPED CALLOUT" +prequest_key_callout --fail a$maxcall user wibble +expect_error EINVAL + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/requesting/noargs/runtest.sh b/tests/keyctl/requesting/noargs/runtest.sh new file mode 100644 index 0000000000..425512218f --- /dev/null +++ b/tests/keyctl/requesting/noargs/runtest.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +if [ $skip_install_required -eq 1 ] +then + echo "++++ SKIPPING TEST" >$OUTPUTFILE + marker "SKIP BECAUSE TEST REQUIRES FULL INSTALL (for /sbin/request-key)" + toolbox_report_result $TEST PASS + exit 0 +else + echo "++++ BEGINNING TEST" >$OUTPUTFILE +fi + +marker "NO ARGS" +expect_args_error keyctl request +expect_args_error keyctl request2 +expect_args_error keyctl prequest2 + +marker "ONE ARG" +expect_args_error keyctl request 0 +expect_args_error keyctl request2 0 +expect_args_error keyctl prequest2 0 + +marker "TWO ARGS" +expect_args_error keyctl request2 0 0 + +marker "FOUR ARGS" +expect_args_error keyctl request 0 0 0 0 +expect_args_error keyctl prequest2 0 0 0 0 + +marker "FIVE ARGS" +expect_args_error keyctl request2 0 0 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/requesting/piped/runtest.sh b/tests/keyctl/requesting/piped/runtest.sh new file mode 100644 index 0000000000..029ae08169 --- /dev/null +++ b/tests/keyctl/requesting/piped/runtest.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +if [ $skip_install_required -eq 1 ] +then + echo "++++ SKIPPING TEST" >$OUTPUTFILE + marker "SKIP BECAUSE TEST REQUIRES FULL INSTALL (for /sbin/request-key)" + toolbox_report_result $TEST PASS + exit 0 +else + echo "++++ BEGINNING TEST" >$OUTPUTFILE +fi + +set_gc_delay 10 + +# create a pair of keyrings to play in +marker "CREATE KEYRINGS" +create_keyring "sandbox" @s +expect_keyid keyringid + +# check that we can't yet request a non-existent key +marker "CHECK REQUEST FAILS" +request_key --fail user lizard $keyringid +expect_error ENOKEY + +# add a user key to the first keyring +marker "ADD USER KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# request the key +marker "REQUEST KEY" +request_key user lizard +expect_keyid keyid2 $keyid + +# remove the key from the keyring +marker "DETACH KEY FROM KEYRING" +unlink_key $keyid $keyringid + +# request a key from /sbin/request-key to the session keyring +marker "PIPED CALL OUT REQUEST KEY TO SESSION" +prequest_key_callout gizzard user debug:lizard +expect_keyid keyid + +# should have appeared in the session keyring +marker "CHECK ATTACHMENT TO SESSION KEYRING" +list_keyring @s +expect_keyring_rlist rlist $keyid + +# rerequesting should pick up that key again +marker "REDO PIPED CALL OUT REQUEST KEY TO SESSION" +prequest_key_callout gizzard user debug:lizard +expect_keyid keyid2 $keyid + +# remove the key from the session +# - it was installed twice +# - once by request_key's keyring arg +# - once from the instantiation call +# but it will only have one link +marker "DETACH KEY FROM SESSION" +unlink_key --wait $keyid @s +unlink_key --fail $keyid @s +expect_error ENOKEY + +# request a key from /sbin/request-key to the keyring we made +marker "PIPED CALL OUT REQUEST KEY TO KEYRING" +prequest_key_callout gizzard user debug:lizard $keyringid +expect_keyid keyid + +# should have appeared once each in the sandbox and session keyrings +marker "CHECK ATTACHMENT TO KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +marker "CHECK ATTACHMENT TO SESSION" +list_keyring @s +expect_keyring_rlist rlist $keyid + +# rerequesting should pick up that key again +marker "REDO PIPED CALL OUT REQUEST KEY TO KEYRING" +prequest_key_callout gizzard user debug:lizard $keyringid +expect_keyid keyid2 $keyid + +# remove the key from the session +marker "DETACH KEY" +unlink_key $keyid $keyringid +unlink_key --wait $keyid @s +unlink_key --fail $keyid @s +expect_error ENOKEY + +# remove the keyrings we added +marker "UNLINK KEYRINGS" +unlink_key $keyringid @s + +set_gc_delay $orig_gc_delay + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/requesting/valid/runtest.sh b/tests/keyctl/requesting/valid/runtest.sh new file mode 100644 index 0000000000..e49fb0f27e --- /dev/null +++ b/tests/keyctl/requesting/valid/runtest.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +if [ $skip_install_required -eq 1 ] +then + echo "++++ SKIPPING TEST" >$OUTPUTFILE + marker "SKIP BECAUSE TEST REQUIRES FULL INSTALL (for /sbin/request-key)" + toolbox_report_result $TEST PASS + exit 0 +else + echo "++++ BEGINNING TEST" >$OUTPUTFILE +fi + +set_gc_delay 10 + +# create a pair of keyrings to play in +marker "CREATE KEYRINGS" +create_keyring "sandbox" @s +expect_keyid keyringid + +# check that we can't yet request a non-existent key +marker "CHECK REQUEST FAILS" +request_key --fail user lizard $keyringid +expect_error ENOKEY + +# add a user key to the first keyring +marker "ADD USER KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# request the key +marker "REQUEST KEY" +request_key user lizard +expect_keyid keyid2 $keyid + +# remove the key from the keyring +marker "DETACH KEY FROM KEYRING" +unlink_key $keyid $keyringid + +# request a key from /sbin/request-key to the session keyring +marker "CALL OUT REQUEST KEY TO SESSION" +request_key_callout user debug:lizard gizzard +expect_keyid keyid + +# should have appeared in the session keyring +marker "CHECK ATTACHMENT TO SESSION KEYRING" +list_keyring @s +expect_keyring_rlist rlist $keyid + +# rerequesting should pick up that key again +marker "REDO CALL OUT REQUEST KEY TO SESSION" +request_key_callout user debug:lizard gizzard +expect_keyid keyid2 $keyid + +# remove the key from the session +# - it was installed twice +# - once by request_key's keyring arg +# - once from the instantiation call +# but it will only have one link +marker "DETACH KEY FROM SESSION" +unlink_key --wait $keyid @s +unlink_key --fail $keyid @s +expect_error ENOKEY + +# request a key from /sbin/request-key to the keyring we made +marker "CALL OUT REQUEST KEY TO KEYRING" +request_key_callout user debug:lizard gizzard $keyringid +expect_keyid keyid + +# should have appeared once each in the sandbox and session keyrings +marker "CHECK ATTACHMENT TO KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +marker "CHECK ATTACHMENT TO SESSION" +list_keyring @s +expect_keyring_rlist rlist $keyid + +# rerequesting should pick up that key again +marker "REDO CALL OUT REQUEST KEY TO KEYRING" +request_key_callout user debug:lizard gizzard $keyringid +expect_keyid keyid2 $keyid + +# remove the key from the session +marker "DETACH KEY" +unlink_key $keyid $keyringid +unlink_key --wait $keyid @s +unlink_key --fail $keyid @s +expect_error ENOKEY + +# remove the keyrings we added +marker "UNLINK KEYRINGS" +unlink_key $keyringid @s + +set_gc_delay $orig_gc_delay + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/restrict/bad-args/runtest.sh b/tests/keyctl/restrict/bad-args/runtest.sh new file mode 100644 index 0000000000..8cd073e355 --- /dev/null +++ b/tests/keyctl/restrict/bad-args/runtest.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +# ---- do the actual testing ---- + +if [ $have_restrict_keyring = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF KEYRING RESTRICTION" + exit 0 +fi + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring for CA keys +marker "ADD CA KEYRING" +create_keyring cakeyring @s +expect_keyid cakeyringid + +# create a keyring +marker "ADD KEYRING TO RESTRICT" +create_keyring restrict @s +expect_keyid restrictid + +# invalid payload +marker "INVALID EXTRA PARAMETER 1" +restrict_keyring --fail $restrictid "asymmetric" "key_or_keyring:$cakeyringid:bad_param" + +marker "INVALID EXTRA PARAMETER 2" +restrict_keyring --fail $restrictid "asymmetric" "builtin_trusted:bad_param" + +marker "INVALID RESTRICT METHOD" +restrict_keyring --fail $restrictid "asymmetric" "no_such_method:$cakeyringid" + +marker "INVALID KEY TYPE" +restrict_keyring --fail $restrictid "not_a_key_type" "builtin_trusted" + +marker "INVALID KEY ID" +restrict_keyring --fail $restrictid "asymmetric" "key_or_keyring:abcxyz" + +# invalid key option +marker "USE KEY ID 0 FOR KEYRING" +restrict_keyring --fail $restrictid "asymmetric" "key_or_keyring:0" + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/restrict/valid/runtest.sh b/tests/keyctl/restrict/valid/runtest.sh new file mode 100644 index 0000000000..2ed1eaf760 --- /dev/null +++ b/tests/keyctl/restrict/valid/runtest.sh @@ -0,0 +1,512 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +if [ $have_restrict_keyring = 0 ] +then + toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF KEYRING RESTRICTION" + exit 0 +fi + +# ---- certs ---- +# Note: 2044-03-06 expiration + +# Root CA 1 +cacert1="\x30\x82\x03\xac\x30\x82\x02\x94\xa0\x03\x02\x01\x02\x02\x09\x00" +cacert1+="\x8d\x38\x41\x1b\x39\xdd\x00\xf8\x30\x0d\x06\x09\x2a\x86\x48\x86" +cacert1+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x41\x31\x0d\x30\x0b\x06\x03\x55" +cacert1+="\x04\x0a\x0c\x04\x4f\x72\x67\x31\x31\x10\x30\x0e\x06\x03\x55\x04" +cacert1+="\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x31\x31\x1e\x30\x1c\x06\x09" +cacert1+="\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x31\x40\x65" +cacert1+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36" +cacert1+="\x31\x30\x31\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30" +cacert1+="\x33\x30\x36\x32\x32\x35\x34\x32\x35\x5a\x30\x41\x31\x0d\x30\x0b" +cacert1+="\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x31\x31\x10\x30\x0e\x06" +cacert1+="\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x31\x31\x1e\x30" +cacert1+="\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61" +cacert1+="\x31\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01" +cacert1+="\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" +cacert1+="\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc4\x38" +cacert1+="\x65\x78\x96\x72\x2b\x81\x11\x01\xea\xc0\x30\xe9\xfd\x8f\xa4\x34" +cacert1+="\x49\x0e\x39\x94\x4c\x11\x6f\xa2\x95\xe3\x93\xb9\xdd\x8c\x7f\x8c" +cacert1+="\xb5\xad\xe3\x62\x08\x4f\x8d\x52\x64\xfa\xcb\xdb\xe3\x3b\x58\xc3" +cacert1+="\x71\x3d\x5e\xa3\x4f\xee\xcc\xe4\x7f\x33\xf6\xda\x76\x36\x49\x3b" +cacert1+="\x96\x87\xdb\x24\x77\xf7\x03\xd0\x9b\x58\x4c\x28\x74\x86\x7e\xc2" +cacert1+="\xd2\xea\x34\x67\xdc\xce\x16\x67\xef\xa6\x1e\xbf\xd5\xe1\x55\x0a" +cacert1+="\xa3\x2f\x3b\xe5\x3d\xd6\xdb\x5c\xe8\x6b\xb9\x09\x16\xbe\x5e\x39" +cacert1+="\xdd\xfb\xd6\x60\xfd\x41\x7b\xfa\xe5\x22\x34\x73\xcd\xcd\x71\xd0" +cacert1+="\xca\xbc\xdf\x4d\x60\xb0\x16\xf2\x66\xe0\x79\x1a\xb1\x79\xed\xe2" +cacert1+="\xa8\x21\xec\x7a\xc0\x65\x72\x04\xae\x03\x6a\x34\x8f\x52\x1b\x7d" +cacert1+="\x13\xd6\x01\xb4\x12\x3f\xc0\x00\x9d\x7d\x47\xf2\x2b\x7a\x34\x6c" +cacert1+="\xac\x70\xf0\xcc\xd7\x69\x36\x4e\x77\x8e\x7b\xdb\xa9\xeb\xc7\xfc" +cacert1+="\x47\x2c\x74\xad\x4c\x03\x74\xe1\xa6\x60\x9f\xe1\xc5\xf1\xb4\xa4" +cacert1+="\x65\xbf\xb9\x74\x9c\x22\x36\x8c\xd5\x9e\xef\xdd\x23\x9d\x49\x37" +cacert1+="\x8d\x7a\xdb\xf1\x63\x23\x7e\x06\x8e\x96\x66\x2f\xbd\x5e\xf2\x53" +cacert1+="\xb4\xc7\xb3\x0c\xb2\x85\x46\xf5\x4c\xec\x92\x38\x5d\x33\x02\x03" +cacert1+="\x01\x00\x01\xa3\x81\xa6\x30\x81\xa3\x30\x0f\x06\x03\x55\x1d\x13" +cacert1+="\x04\x08\x30\x06\x01\x01\xff\x02\x01\x00\x30\x1d\x06\x03\x55\x1d" +cacert1+="\x0e\x04\x16\x04\x14\xa6\x90\x37\x33\x55\x73\x58\xcd\x8a\x4c\xaa" +cacert1+="\xcb\x4a\xe7\x54\x0e\x00\x81\x7e\xe8\x30\x71\x06\x03\x55\x1d\x23" +cacert1+="\x04\x6a\x30\x68\x80\x14\xa6\x90\x37\x33\x55\x73\x58\xcd\x8a\x4c" +cacert1+="\xaa\xcb\x4a\xe7\x54\x0e\x00\x81\x7e\xe8\xa1\x45\xa4\x43\x30\x41" +cacert1+="\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x31\x31" +cacert1+="\x10\x30\x0e\x06\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72" +cacert1+="\x31\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01" +cacert1+="\x16\x0f\x63\x61\x31\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f" +cacert1+="\x6d\x82\x09\x00\x8d\x38\x41\x1b\x39\xdd\x00\xf8\x30\x0d\x06\x09" +cacert1+="\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00" +cacert1+="\x85\x84\x97\x71\xd8\x1a\xb5\xc0\x90\xbb\x95\x14\x19\xd7\x76\x30" +cacert1+="\xf8\x42\x02\xad\x7b\x1f\x73\xbe\xf4\x78\x9d\x87\xb1\x99\xcf\xc7" +cacert1+="\x59\xb4\x2f\xf7\x8a\xda\xbb\x07\xa1\x76\x29\x30\x4e\x41\x0f\x7e" +cacert1+="\x97\x9c\xba\xfd\xf4\xc5\x08\x3c\x14\xb0\x7a\x6f\xf1\x67\xb2\xf9" +cacert1+="\xb1\x46\xc8\x83\xfd\xa6\x4f\xc6\x25\x76\xf2\xc1\x11\x92\xba\xfb" +cacert1+="\x25\x85\xe4\x1b\xc6\x92\x79\x63\xc0\x8a\xe7\xfb\x48\x69\x4d\x83" +cacert1+="\x20\xb8\x3d\x8a\x55\xfa\x6d\xe9\x7b\xd1\x96\x75\x0a\x0f\x63\x53" +cacert1+="\x01\x00\xf7\xc3\x28\xa1\xd8\x9e\x41\x6e\x52\xb9\x00\x43\x09\xf2" +cacert1+="\x91\xb7\x06\x5f\xd2\x0c\x42\x03\x67\xd6\x77\xb2\xce\x96\xd4\x73" +cacert1+="\x58\x59\xd9\xf8\x47\xb7\xc7\x23\x96\x65\xeb\xdf\x55\x1b\x1f\xc7" +cacert1+="\xa3\x7c\x7a\x2a\x1b\x95\xec\xf8\xa0\x26\xba\x81\x4b\x94\xb6\x5f" +cacert1+="\xa9\x7d\xb8\x0c\x46\x11\x3a\x70\x3c\xd5\x7c\x60\xd2\x38\x42\x0f" +cacert1+="\xe1\x70\x69\xdc\x4f\x5a\xf9\x65\x45\x97\xbf\x49\xe1\xd2\x59\x5c" +cacert1+="\x8a\xf4\xc4\xe0\x72\xb7\x2d\x4e\xbd\xe6\x69\x9d\x68\x8c\x9c\xfe" +cacert1+="\x4a\xf7\xc0\x0d\xc9\xb9\x92\x50\xff\x5c\x9b\xb9\x9a\x51\xdd\x6c" +cacert1+="\x91\xc7\xa9\x88\x83\xcc\xed\x49\xe7\xcf\x41\xe1\xef\x76\x55\x62" + +# Root CA 2 +cacert2="\x30\x82\x03\xac\x30\x82\x02\x94\xa0\x03\x02\x01\x02\x02\x09\x00" +cacert2+="\xa7\x75\xd3\x8a\xe3\x8d\x8e\x3c\x30\x0d\x06\x09\x2a\x86\x48\x86" +cacert2+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x41\x31\x0d\x30\x0b\x06\x03\x55" +cacert2+="\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04" +cacert2+="\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09" +cacert2+="\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65" +cacert2+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36" +cacert2+="\x31\x30\x31\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30" +cacert2+="\x33\x30\x36\x32\x32\x35\x34\x32\x35\x5a\x30\x41\x31\x0d\x30\x0b" +cacert2+="\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06" +cacert2+="\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30" +cacert2+="\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61" +cacert2+="\x32\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01" +cacert2+="\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" +cacert2+="\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa5\xdf" +cacert2+="\x33\xab\xa3\xb0\x60\xb5\x8e\x7f\xdf\x58\xfd\x71\xa0\x39\x40\x7a" +cacert2+="\x4f\xf6\xc8\xec\xbe\xa7\x18\x4b\x4d\xd3\x73\x52\xca\xfa\xee\xa0" +cacert2+="\x06\x21\xd8\x52\xf5\x40\x62\xc1\x4e\xd3\x6d\x9c\xc3\x12\x57\x78" +cacert2+="\x15\x68\x67\x61\x4e\xfd\xfa\x71\xb6\xdc\xf9\x77\x36\x8f\x51\x1c" +cacert2+="\x0a\x19\x42\x8a\x95\x6c\xf8\x2f\xd2\x1a\xe7\x39\x4c\xcd\x07\x62" +cacert2+="\x12\x36\x8a\x5b\x97\x9b\x7a\x94\xce\x4c\x99\x36\x88\xc6\x17\x2c" +cacert2+="\x91\xcd\x95\xa1\x48\x76\x9a\x22\xf8\x87\x84\xde\xc6\xae\x03\xa9" +cacert2+="\x34\x93\xd8\xb3\x4c\x5f\xfb\x8b\x12\x0a\xc5\xad\xa4\x40\x56\xb6" +cacert2+="\x44\x54\x50\xcb\x57\xe0\xb3\x77\x9d\xe2\x10\xa6\xb8\xfc\x21\x67" +cacert2+="\x90\x61\x30\xbe\xfc\x84\xb3\x3a\x1f\x31\x1a\x8a\xc6\x37\x29\x3a" +cacert2+="\x82\x8a\x1a\xa0\xcb\xa0\x65\x8a\x0e\x7d\xae\x03\x5c\x35\xa4\x64" +cacert2+="\x5a\x79\xdd\xe1\xf7\x87\x91\xac\xe1\x67\x76\x48\x17\x05\x57\x01" +cacert2+="\xa6\xf9\x36\x09\x3c\x0e\xc2\xa3\xf9\xfb\xbb\x4d\x05\xf3\x92\x42" +cacert2+="\xf5\x4b\x9b\x2c\xab\xd5\xe8\x7c\x0a\x4a\xe6\x85\xba\x95\x28\xc1" +cacert2+="\x04\x46\x94\x15\x1a\xe3\x61\xd5\x0b\x17\x50\xa7\x92\x98\xaa\x6a" +cacert2+="\xe8\x91\x91\xae\x02\x6e\x35\x4b\x41\xcb\xbe\x02\xad\xb1\x02\x03" +cacert2+="\x01\x00\x01\xa3\x81\xa6\x30\x81\xa3\x30\x0f\x06\x03\x55\x1d\x13" +cacert2+="\x04\x08\x30\x06\x01\x01\xff\x02\x01\x00\x30\x1d\x06\x03\x55\x1d" +cacert2+="\x0e\x04\x16\x04\x14\x44\xfb\x94\xd9\x3d\x4a\x0e\x82\x59\xc6\x90" +cacert2+="\xa1\x38\xfa\x0e\x8c\xc4\x4a\x4f\x77\x30\x71\x06\x03\x55\x1d\x23" +cacert2+="\x04\x6a\x30\x68\x80\x14\x44\xfb\x94\xd9\x3d\x4a\x0e\x82\x59\xc6" +cacert2+="\x90\xa1\x38\xfa\x0e\x8c\xc4\x4a\x4f\x77\xa1\x45\xa4\x43\x30\x41" +cacert2+="\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31" +cacert2+="\x10\x30\x0e\x06\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72" +cacert2+="\x32\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01" +cacert2+="\x16\x0f\x63\x61\x32\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f" +cacert2+="\x6d\x82\x09\x00\xa7\x75\xd3\x8a\xe3\x8d\x8e\x3c\x30\x0d\x06\x09" +cacert2+="\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00" +cacert2+="\x62\xf7\xbc\xd7\x49\x2d\xa2\x47\x8b\x28\xb3\xd4\x3e\xe6\x76\x00" +cacert2+="\x12\xe6\x15\xe2\xf7\xa5\x20\x0f\xcf\xbd\xa9\x8a\x0f\x97\x38\x57" +cacert2+="\xac\x69\x5f\x76\x90\xdb\x52\x0a\x55\xbe\x6a\x34\xb1\x3e\xef\x45" +cacert2+="\xed\x0a\x55\xe9\x46\xdc\x2c\xe2\xd3\x24\x7e\x3b\x10\x38\x72\x38" +cacert2+="\x98\xae\xda\x55\xe0\x33\x7f\x86\x56\xbb\x12\x7a\x5b\x44\x4b\x8d" +cacert2+="\xf5\xd3\xfb\x83\x1b\x07\x08\xab\x0f\x95\x07\x98\x60\xa1\x6e\x6c" +cacert2+="\x0f\xb8\xa2\xe1\x74\xf4\x43\xd3\x91\x8e\xa0\x40\xea\x9b\x54\x3d" +cacert2+="\x71\x1f\x75\xb4\x59\x67\x47\x95\xeb\x2e\xdc\x37\x1d\xd2\xd8\xe6" +cacert2+="\xe5\x3a\x86\x60\xa4\x2a\xb4\x6e\x7e\x34\x09\x2b\x42\x0e\xe7\x3b" +cacert2+="\x83\x5d\xdd\xee\xc9\xa4\x6c\x65\x49\x0b\x59\x1b\x46\xf1\x46\x2e" +cacert2+="\xf7\x37\x0f\x06\xa1\x85\x33\x38\xee\x11\x89\x62\x3f\xf6\x42\x5e" +cacert2+="\x1b\x6c\xfd\xcd\x4b\xa0\x8a\x71\x74\x27\xef\xbb\x6e\xbe\x68\xfc" +cacert2+="\xb6\xcd\x88\xfe\x0e\x92\xec\xfe\x60\xe1\x26\xce\xee\x0a\x48\x6c" +cacert2+="\x93\x1f\x85\x9f\xd8\x81\xa0\xd7\xfc\x35\xe6\xad\x63\x97\xf5\x12" +cacert2+="\x2f\xdb\xf6\x38\x54\x0e\x6e\x7d\xcc\x88\x64\xa9\x4f\xc1\x6d\x60" +cacert2+="\x03\x5d\x4c\x72\x6a\xa3\xf1\x29\xaa\x62\xf4\xa1\x04\x38\x78\xcd" + +# Intermediate CA (signed by CA 2) +intcert="\x30\x82\x03\xa9\x30\x82\x02\x91\xa0\x03\x02\x01\x02\x02\x09\x00" +intcert+="\xfe\x1e\xe6\xa8\x4e\x42\xc4\x72\x30\x0d\x06\x09\x2a\x86\x48\x86" +intcert+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x41\x31\x0d\x30\x0b\x06\x03\x55" +intcert+="\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04" +intcert+="\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09" +intcert+="\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65" +intcert+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36" +intcert+="\x31\x30\x31\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30" +intcert+="\x33\x30\x36\x32\x32\x35\x34\x32\x35\x5a\x30\x41\x31\x0d\x30\x0b" +intcert+="\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06" +intcert+="\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30" +intcert+="\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61" +intcert+="\x32\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01" +intcert+="\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" +intcert+="\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe2\x07" +intcert+="\xfb\x98\x1b\x29\xd7\x82\x9c\x64\xce\x81\xfb\x8b\x2d\xe1\x44\xa0" +intcert+="\x0e\x2e\xc9\xb6\xb8\x16\x7d\x9a\xcf\xa4\xb7\x21\x2f\xdc\x4c\x79" +intcert+="\xfe\xe4\x34\xc8\x94\x93\xdf\x5a\xdd\x94\x33\xf8\xda\x0d\x17\xb7" +intcert+="\x0a\x4d\x82\x72\x9a\x6f\xfa\xac\x3f\x4a\x1b\x78\x1a\x99\xa3\x24" +intcert+="\x66\x0b\xc4\x72\x2a\xe0\xb4\xbd\xd5\xa1\x06\xbf\xdb\xd0\xdf\x8b" +intcert+="\x15\xee\xa9\x18\x50\x7a\x83\x53\x21\xf7\xbb\x4b\xce\x57\xe8\x8b" +intcert+="\x02\x9d\x3a\x73\x3e\x5d\x67\xa5\x11\xde\xec\xc2\x4e\xbe\xfe\x09" +intcert+="\x40\xfd\x22\xb5\x2e\xb2\x2b\xe7\x07\x81\x0c\x72\xf3\xbf\x22\x55" +intcert+="\xaa\xb9\x02\xb9\x48\x8c\x89\xb6\xf3\x5d\x27\x9a\xd5\xc2\x47\xf9" +intcert+="\xb9\x0c\xb5\x90\xbf\x8b\xee\xd8\x8c\x3d\x2d\xbf\xa1\xb0\xcf\xe2" +intcert+="\xd9\x44\x9b\x88\x66\xb3\x6e\xec\xe6\xaa\x2c\x67\x2e\x6f\x2b\x23" +intcert+="\xd6\xe2\xa1\xb1\x7a\x0d\xb1\x50\x30\xe4\x22\xec\xbf\x87\x28\xcc" +intcert+="\xa0\x73\x42\x4a\xdc\x5d\x2b\x37\x7e\x43\x63\x59\x01\xaa\x9e\xc4" +intcert+="\x4b\xfa\x05\x38\x4d\xc2\xde\x41\xb1\x60\xd1\x4b\xfd\x89\x9e\xe0" +intcert+="\xdf\xff\x21\x91\x1c\x6f\xba\x10\xba\x15\xe3\x44\xf0\x1f\xd8\x43" +intcert+="\x2e\x03\xc7\xf3\x51\xa3\x36\xfd\x25\x71\x4b\x87\x65\x5b\x02\x03" +intcert+="\x01\x00\x01\xa3\x81\xa3\x30\x81\xa0\x30\x0c\x06\x03\x55\x1d\x13" +intcert+="\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16" +intcert+="\x04\x14\xf5\x71\x46\x2e\x96\x8c\x27\x3e\x47\xef\xba\x8a\x2c\x1c" +intcert+="\xb5\x15\x88\xa7\x24\x14\x30\x71\x06\x03\x55\x1d\x23\x04\x6a\x30" +intcert+="\x68\x80\x14\x44\xfb\x94\xd9\x3d\x4a\x0e\x82\x59\xc6\x90\xa1\x38" +intcert+="\xfa\x0e\x8c\xc4\x4a\x4f\x77\xa1\x45\xa4\x43\x30\x41\x31\x0d\x30" +intcert+="\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e" +intcert+="\x06\x03\x55\x04\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e" +intcert+="\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63" +intcert+="\x61\x32\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x82\x09" +intcert+="\x00\xa7\x75\xd3\x8a\xe3\x8d\x8e\x3c\x30\x0d\x06\x09\x2a\x86\x48" +intcert+="\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x53\xb3\x9a" +intcert+="\xfa\x63\xdb\x3e\x20\x7b\x8a\xa3\xc0\x8e\x31\x18\x80\x6a\x75\x8b" +intcert+="\x9c\xdc\x34\xfb\xc6\xd2\x52\x4b\x60\x17\x33\x72\x62\xa4\xf8\xfd" +intcert+="\x7d\x19\x52\x88\x25\x5b\xbe\x86\x46\x75\x8b\x77\x21\xe7\x47\x98" +intcert+="\xf5\x8b\xbc\x09\x1a\x33\xa8\xdf\xdb\x98\x5a\x92\x40\x74\x3e\x65" +intcert+="\xd8\x9e\x56\x65\xbb\x62\x26\xa7\x32\xe2\x4b\x03\xd5\x16\xbe\xb6" +intcert+="\xa7\x23\xb2\xe7\x36\x4f\x11\x05\xd1\x1c\x12\x70\x35\x70\xcb\xe6" +intcert+="\x99\xf8\x4b\x3a\x87\x27\xe5\xe6\x08\x5f\x06\x7e\x83\x85\x9a\x34" +intcert+="\xc2\x8a\xfa\x52\x82\xf7\xbd\x71\xac\xc9\xec\x9b\x9a\x70\xa6\x6b" +intcert+="\x2e\xee\x62\xa3\x0c\x07\xd2\xbd\x8a\xfc\x8a\x4b\xe9\x4a\xe9\x11" +intcert+="\xdd\x6e\xbb\x94\xb8\x9b\xc7\x79\x4d\x82\xdd\x0f\x62\x1d\x84\xf7" +intcert+="\x00\xec\x37\xe5\x56\x5f\x39\x18\x85\x0e\xef\x20\xdf\x3f\x97\x96" +intcert+="\x03\x84\x50\x21\x9d\xe0\x00\x44\x19\x82\x58\x6b\x79\xfa\x32\x34" +intcert+="\x65\x4b\xed\x36\xae\x1a\xd8\x78\xae\x59\xf0\xb8\xb7\xb0\xe3\xb4" +intcert+="\x23\x71\xe7\xda\x18\xff\x6d\x6e\x3b\x8b\xc8\x13\x52\x1c\xc5\xff" +intcert+="\x66\xfd\xe1\x7a\x28\xac\x3e\xe5\x0e\x80\x03\x91\xce\x30\x2b\x98" +intcert+="\x3b\x71\x2f\x37\x80\xf1\x29\xbc\xdb\x42\xa1\x6e\xd0" + +# End entity cert (signed by CA 2) +signed="\x30\x82\x03\xa3\x30\x82\x02\x8b\xa0\x03\x02\x01\x02\x02\x09\x00" +signed+="\xfe\x1e\xe6\xa8\x4e\x42\xc4\x73\x30\x0d\x06\x09\x2a\x86\x48\x86" +signed+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x41\x31\x0d\x30\x0b\x06\x03\x55" +signed+="\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04" +signed+="\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09" +signed+="\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65" +signed+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36" +signed+="\x31\x30\x31\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30" +signed+="\x33\x30\x36\x32\x32\x35\x34\x32\x35\x5a\x30\x3e\x31\x0c\x30\x0a" +signed+="\x06\x03\x55\x04\x0a\x0c\x03\x4f\x72\x67\x31\x0f\x30\x0d\x06\x03" +signed+="\x55\x04\x03\x0c\x06\x49\x73\x73\x75\x65\x72\x31\x1d\x30\x1b\x06" +signed+="\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x65\x65\x40\x65" +signed+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01\x22\x30\x0d" +signed+="\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01" +signed+="\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\xc7\x25\x7d\x83" +signed+="\xb3\xbb\x04\x04\xae\xc1\x53\x85\xdc\x61\x4f\xb9\x5c\x80\x03\x86" +signed+="\x4c\x1b\xbe\x57\x39\xb0\x43\x09\x37\xce\x5d\x98\xcc\x74\x38\xa8" +signed+="\xf6\x6f\x6a\x9e\x3d\xd6\x88\x62\x61\x35\x7f\x85\x73\x06\x48\x1e" +signed+="\x65\x69\xc3\xf4\xf3\x6e\xa2\x79\xfa\x12\xd0\x80\xb4\x11\xc6\x8f" +signed+="\x13\xb5\xc4\x42\xe0\x22\x54\x4a\x46\x47\xaf\x61\xcb\x35\xd2\xea" +signed+="\xe9\x5e\x0d\x0e\xc1\x36\x72\x6a\xd3\xa0\x4e\xe9\xf1\x9e\xbd\xbd" +signed+="\x21\xd6\x8d\x0b\x24\x7a\x8b\xc1\xcc\x52\x48\xc9\xb5\x4f\x1c\xe0" +signed+="\xaf\xe3\x8b\x24\xbb\x34\x9f\x8f\x03\x13\xe8\x2e\xee\xd4\xda\x17" +signed+="\x25\x3f\x2d\xf3\x7e\x33\x3f\x97\x42\xef\xaf\x4c\x35\xb8\x02\x60" +signed+="\xc0\x4f\x20\xbe\x97\xb7\xd3\xc3\x38\x73\x14\x7d\x68\x2a\xab\x04" +signed+="\x96\x81\xde\xe6\x5a\x03\x1e\xd6\x07\xe8\x0a\x38\xc0\xf0\x2b\x54" +signed+="\xb2\x9b\xbd\x54\x72\x8e\x97\x76\x5e\x4c\x80\xb8\x19\xf8\x69\x17" +signed+="\x99\x41\xd9\x61\xb5\x9d\x4c\x8d\xbb\x19\x5f\x39\x7e\xc9\x19\x8d" +signed+="\xdc\xa4\x21\xf1\x32\xfe\x89\x9a\xa3\x92\xe5\x76\x73\x64\x67\x29" +signed+="\x34\x4a\x31\x02\xaa\x35\xaf\x88\x06\x0b\x63\x4d\xe4\xa2\x1f\xaa" +signed+="\x48\x9f\x85\xf5\xc4\xd4\x03\x52\x29\xb7\x51\x02\x03\x01\x00\x01" +signed+="\xa3\x81\xa0\x30\x81\x9d\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30" +signed+="\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xfc\x91\xdf\xb8" +signed+="\x99\x8a\x5c\x07\xee\xb6\x32\xcc\x79\x0b\x31\x0a\x3a\xca\x65\x23" +signed+="\x30\x71\x06\x03\x55\x1d\x23\x04\x6a\x30\x68\x80\x14\x44\xfb\x94" +signed+="\xd9\x3d\x4a\x0e\x82\x59\xc6\x90\xa1\x38\xfa\x0e\x8c\xc4\x4a\x4f" +signed+="\x77\xa1\x45\xa4\x43\x30\x41\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a" +signed+="\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04\x03\x0c" +signed+="\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09\x2a\x86" +signed+="\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65\x78\x61" +signed+="\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x82\x09\x00\xa7\x75\xd3\x8a\xe3" +signed+="\x8d\x8e\x3c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b" +signed+="\x05\x00\x03\x82\x01\x01\x00\x36\x04\xff\x32\x8c\x5e\x7b\x2d\x99" +signed+="\x2e\x84\x2f\xae\xed\x82\x96\x99\xe1\x18\xe0\x8c\xe9\x61\x3c\x0f" +signed+="\xb1\xd7\x53\x5e\x24\x84\xe7\xe9\x19\xaa\xfe\xed\x21\x82\x3b\x6c" +signed+="\xf4\xaa\xe9\x0a\x84\x88\x84\x1a\x46\xc7\xc8\x00\x3f\x94\x86\x2c" +signed+="\xc5\x28\xa3\xac\xbd\x8a\x6f\x53\x38\x7f\x06\x12\x51\xbc\x1b\x4d" +signed+="\x2d\xcb\x63\x65\x4b\x74\x42\x4d\xc8\xd6\x56\x03\xfe\x81\x9b\x52" +signed+="\x3a\xc8\xb7\xcc\xd0\x03\x85\xad\x30\x7c\x3d\x73\xd1\x06\x16\x70" +signed+="\x4a\xcc\x15\xa4\x83\xcf\x54\x0f\xd7\xab\x9a\xf0\xb9\x39\x80\x06" +signed+="\x7f\x75\x45\x2e\xec\x76\xb2\xbd\xb8\xfd\xe3\x38\xdb\x18\x2f\x09" +signed+="\xea\xe3\x1c\xfe\xd2\x6c\xab\xae\xaa\x9c\x47\xfb\xe5\xd6\x0d\xd6" +signed+="\x6f\x42\x5f\x0b\xde\xa3\xc1\xb5\xf7\xaf\x5a\xf1\xab\xe8\xc4\x7c" +signed+="\xeb\xaf\x48\xe4\x5d\x61\xa1\x5b\xf1\x28\x8f\xd0\x58\x1d\x9f\x64" +signed+="\x8b\xf8\xf0\x33\xa6\xeb\x0b\xb2\xc5\x62\x09\xd8\x4c\x72\x4d\xae" +signed+="\x04\xc7\x45\xeb\xdc\xa6\xb2\xf0\xfb\x2b\xb0\x81\xb6\x4f\x3e\x12" +signed+="\x56\x61\x42\x74\x64\x66\x90\xb5\x72\x8f\x09\x8a\x8d\x6c\xc7\x02" +signed+="\x0a\xc8\x51\xe0\x11\x00\x3c\xad\xf2\x5b\x29\xeb\x60\x2f\xb4\xdd" +signed+="\x73\xc0\xb7\xdb\x1f\x6d\xb1" + +# End entity cert (signed by intermediate CA) +intsigned="\x30\x82\x03\xa4\x30\x82\x02\x8c\xa0\x03\x02\x01\x02\x02\x09\x00" +intsigned+="\xe5\x03\xc2\x77\xbb\xb3\x95\x45\x30\x0d\x06\x09\x2a\x86\x48\x86" +intsigned+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x41\x31\x0d\x30\x0b\x06\x03\x55" +intsigned+="\x04\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04" +intsigned+="\x03\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09" +intsigned+="\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65" +intsigned+="\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36" +intsigned+="\x31\x30\x31\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30" +intsigned+="\x33\x30\x36\x32\x32\x35\x34\x32\x35\x5a\x30\x3f\x31\x0c\x30\x0a" +intsigned+="\x06\x03\x55\x04\x0a\x0c\x03\x4f\x72\x67\x31\x0f\x30\x0d\x06\x03" +intsigned+="\x55\x04\x03\x0c\x06\x49\x73\x73\x75\x65\x72\x31\x1e\x30\x1c\x06" +intsigned+="\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x65\x65\x63\x40" +intsigned+="\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01\x22\x30" +intsigned+="\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82" +intsigned+="\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x92\xfd\x9d\x2c" +intsigned+="\x31\xf2\xac\x18\xb3\x73\x7c\xf3\x7c\xd1\xea\x59\x48\xb0\xde\x55" +intsigned+="\xc7\xa3\xf6\xbd\xa4\xd7\x34\x86\xb3\x2d\x38\x8c\xb4\x44\xec\xd0" +intsigned+="\x02\xcf\x9a\xff\xf3\xa7\x9b\x44\xd5\x83\x8a\xb5\x0c\x44\xde\x68" +intsigned+="\x14\xc3\x65\xeb\x34\x64\x90\xff\x00\x7e\x1e\x2e\x97\x12\xf3\x94" +intsigned+="\x24\x08\x73\xeb\x59\x2d\x54\x35\x76\x7a\x43\x97\x7c\xe4\xe8\xa0" +intsigned+="\x2c\x20\x5e\x5b\xc8\xaf\xa7\xf7\x0e\x3e\xc4\x4a\x2c\xd6\xd4\x3a" +intsigned+="\x0e\x20\x70\x33\x57\x46\x12\xbe\x89\xd2\x4a\x17\xde\xca\x9a\xde" +intsigned+="\x7f\x40\xa9\x06\x27\x61\xe2\x4b\x3f\xda\x24\x02\x20\x06\x83\xb2" +intsigned+="\x87\x7e\xa0\xf6\xc7\xfd\x4e\x91\xba\x9f\x32\x9b\x61\x32\x0a\xc0" +intsigned+="\xc1\x21\xaa\xce\xfc\xae\x22\xd9\x85\xc6\xeb\x94\xca\xe3\xb3\x05" +intsigned+="\xf6\x00\xa6\xe4\xc8\xf3\xfe\x3e\xb0\xc0\x4d\x1c\x13\x44\xa2\x61" +intsigned+="\xb0\x3d\xaa\xda\xbe\x60\x69\xbc\x91\x24\x96\x33\x0f\x6d\x12\x51" +intsigned+="\x32\x27\xb3\x5e\x04\x02\x81\x5c\x48\x6b\x50\xcb\xad\x91\xe1\xfa" +intsigned+="\xb1\x00\x56\x00\x22\xd6\x1a\xb6\xad\xf0\x1c\x1a\x30\x58\x0c\x45" +intsigned+="\x6e\xd8\xcc\x50\xbb\xe1\x14\x8a\x20\x6b\xc3\x0b\x32\x66\x43\x9e" +intsigned+="\xf4\x49\x52\x79\x41\x59\x49\xff\x2d\xe1\xbc\x49\x02\x03\x01\x00" +intsigned+="\x01\xa3\x81\xa0\x30\x81\x9d\x30\x09\x06\x03\x55\x1d\x13\x04\x02" +intsigned+="\x30\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf7\xde\x3c" +intsigned+="\x11\x91\x03\x2f\x77\xa7\x71\x1b\xa3\xa1\x73\x36\x01\x66\x29\xcc" +intsigned+="\x2b\x30\x71\x06\x03\x55\x1d\x23\x04\x6a\x30\x68\x80\x14\xf5\x71" +intsigned+="\x46\x2e\x96\x8c\x27\x3e\x47\xef\xba\x8a\x2c\x1c\xb5\x15\x88\xa7" +intsigned+="\x24\x14\xa1\x45\xa4\x43\x30\x41\x31\x0d\x30\x0b\x06\x03\x55\x04" +intsigned+="\x0a\x0c\x04\x4f\x72\x67\x32\x31\x10\x30\x0e\x06\x03\x55\x04\x03" +intsigned+="\x0c\x07\x49\x73\x73\x75\x65\x72\x32\x31\x1e\x30\x1c\x06\x09\x2a" +intsigned+="\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x63\x61\x32\x40\x65\x78" +intsigned+="\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x82\x09\x00\xfe\x1e\xe6\xa8" +intsigned+="\x4e\x42\xc4\x72\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" +intsigned+="\x0b\x05\x00\x03\x82\x01\x01\x00\xc3\xce\xd4\x43\x63\x19\xa3\xa2" +intsigned+="\x4c\x84\x26\xeb\x62\x88\xb7\xcd\xe1\x83\xff\x61\x49\x54\xcf\x2e" +intsigned+="\xad\x6e\x68\x1f\xe5\x2a\xd8\xd5\x5a\x92\x1a\xa4\x7a\x23\x74\x0a" +intsigned+="\x7d\x75\xf6\xc6\x3c\x79\x14\xe6\x52\xb1\xfd\xdb\x42\x04\xdb\x79" +intsigned+="\xc4\xfa\x74\x4b\x26\x26\x01\xfc\x70\xc4\xa5\xfb\xd4\x89\x63\xd7" +intsigned+="\xf5\x9b\xd5\xae\xf5\xd4\x8b\x3a\x3c\xc6\x51\x36\xff\xf8\xb3\x21" +intsigned+="\x68\x4d\xa2\xd2\x92\xe2\x5e\x78\xc6\x4a\x10\xa5\x88\x7c\x1e\xf2" +intsigned+="\x1c\x68\xdc\xe9\x8f\x58\xb1\xa6\xe5\xc6\x4d\xdb\xf7\xc9\x66\x2f" +intsigned+="\xd8\xc7\x86\x83\x63\x14\xf3\x4e\x2a\x39\xf2\x2d\x50\x3a\x53\x7d" +intsigned+="\xfb\x91\xe4\x54\x7d\x33\xdf\x13\x63\x6f\x21\x9d\x12\xad\x48\x5d" +intsigned+="\xf9\x41\xa1\x10\x80\xcd\x28\x9a\x4c\x82\x60\xae\x66\xc4\x85\x6f" +intsigned+="\x55\x1e\x5d\x97\x49\x60\x1d\xdb\x26\x31\x1e\x0f\x08\x80\x11\x30" +intsigned+="\x0f\x75\xad\x32\xfd\x28\xe4\xb9\x09\x30\x26\x32\xcd\x32\x83\x0c" +intsigned+="\x4b\x51\x4e\x68\x70\xfc\x5b\x52\x9f\x3f\x27\xe7\xe9\xe2\x89\xa9" +intsigned+="\xc0\x45\x42\xc7\xb7\x6d\x93\xb4\x02\xf4\xdb\xfd\x1c\x32\xc9\x25" +intsigned+="\x4d\x4d\xff\xab\x72\xb5\x78\xb9\xd1\xcc\xdb\x73\x39\x6f\x7c\x84" +intsigned+="\x6c\xc9\xf1\xb5\xcb\x81\x53\x8c" + +# Self-signed cert +selfsign="\x30\x82\x03\x9d\x30\x82\x02\x85\xa0\x03\x02\x01\x02\x02\x09\x00" +selfsign+="\xe1\xaa\x44\xda\xac\x8f\x12\x04\x30\x0d\x06\x09\x2a\x86\x48\x86" +selfsign+="\xf7\x0d\x01\x01\x0b\x05\x00\x30\x3e\x31\x0c\x30\x0a\x06\x03\x55" +selfsign+="\x04\x0a\x0c\x03\x4f\x72\x67\x31\x0f\x30\x0d\x06\x03\x55\x04\x03" +selfsign+="\x0c\x06\x49\x73\x73\x75\x65\x72\x31\x1d\x30\x1b\x06\x09\x2a\x86" +selfsign+="\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x73\x73\x40\x65\x78\x61\x6d" +selfsign+="\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x36\x31\x30\x31" +selfsign+="\x39\x32\x32\x35\x34\x32\x35\x5a\x17\x0d\x34\x34\x30\x33\x30\x36" +selfsign+="\x32\x32\x35\x34\x32\x35\x5a\x30\x3e\x31\x0c\x30\x0a\x06\x03\x55" +selfsign+="\x04\x0a\x0c\x03\x4f\x72\x67\x31\x0f\x30\x0d\x06\x03\x55\x04\x03" +selfsign+="\x0c\x06\x49\x73\x73\x75\x65\x72\x31\x1d\x30\x1b\x06\x09\x2a\x86" +selfsign+="\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x73\x73\x40\x65\x78\x61\x6d" +selfsign+="\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x82\x01\x22\x30\x0d\x06\x09\x2a" +selfsign+="\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30" +selfsign+="\x82\x01\x0a\x02\x82\x01\x01\x00\xba\x2e\x4e\x75\x7a\x1f\xf9\xe7" +selfsign+="\x58\xda\x54\xb1\xf5\xcf\x26\xad\x1a\x5d\xd6\xa5\xf7\xf1\xe4\xef" +selfsign+="\x2d\x8c\xc9\x03\x69\x39\x55\xbd\xa2\xb1\x8b\x00\xf1\x08\x21\x4b" +selfsign+="\x1d\x47\xff\x88\x2c\x56\x1a\x90\x2b\xaa\x32\x88\xa0\xa7\xd8\x58" +selfsign+="\x5c\x74\xde\xaa\x8a\x17\x89\xc9\x3c\x6b\x17\x97\x90\x82\x8c\xf6" +selfsign+="\xa1\x1e\x1a\x6e\x30\xb3\x56\xad\x4a\xdb\x50\xb3\x0b\xe2\x70\xdd" +selfsign+="\xf2\x61\xf8\xa6\x8c\xf7\xcb\x2a\xb0\xd3\xd3\x14\x3e\xe6\x80\xe3" +selfsign+="\x32\xd9\x25\x5c\x8f\x40\x5e\xb4\x71\x33\xd8\xfc\x1c\x9f\xd0\x95" +selfsign+="\x90\x56\xe6\x7d\x4e\x39\x6d\xc1\x3a\xd9\x28\x9f\x40\xe7\x13\x17" +selfsign+="\x7c\x9d\xdd\x6b\xd0\xf7\xe9\x68\xfa\xc2\x28\xb3\x45\x12\x5b\xfe" +selfsign+="\x57\x72\x6c\x86\x9f\x18\xd6\xb6\x6b\xc8\x7c\x12\xca\x4e\x2f\xc7" +selfsign+="\x25\x88\x92\x4e\x9f\xdd\x02\x6d\x37\x82\xf1\x8b\xd3\xf5\x6f\xf1" +selfsign+="\x4c\xfa\xd8\x80\xe2\x23\xc6\xb7\x8f\x1e\x76\x45\x91\xc5\xf6\x30" +selfsign+="\x48\x9f\xdb\x56\x31\x24\xed\xc8\xfd\x85\x21\x53\x79\xb0\x96\x51" +selfsign+="\x5a\x1e\x82\x21\x95\x5a\x7f\xf1\x32\x25\x7a\x3c\xb4\x16\x6f\x6e" +selfsign+="\xb8\xf2\xf2\xed\x75\xe9\x8b\x7a\xdb\xee\x5c\xf2\x63\x92\x47\xb7" +selfsign+="\x7f\x07\x53\x8e\x14\x5c\x9e\xb3\x02\x03\x01\x00\x01\xa3\x81\x9d" +selfsign+="\x30\x81\x9a\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x1d" +selfsign+="\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6a\x1d\x32\xc2\x5a\x0e\x9d" +selfsign+="\xef\xb3\x59\x2e\x0e\xcf\x2e\x99\x4e\x30\x8d\x61\x1a\x30\x6e\x06" +selfsign+="\x03\x55\x1d\x23\x04\x67\x30\x65\x80\x14\x6a\x1d\x32\xc2\x5a\x0e" +selfsign+="\x9d\xef\xb3\x59\x2e\x0e\xcf\x2e\x99\x4e\x30\x8d\x61\x1a\xa1\x42" +selfsign+="\xa4\x40\x30\x3e\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x0c\x03\x4f" +selfsign+="\x72\x67\x31\x0f\x30\x0d\x06\x03\x55\x04\x03\x0c\x06\x49\x73\x73" +selfsign+="\x75\x65\x72\x31\x1d\x30\x1b\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01" +selfsign+="\x09\x01\x16\x0e\x73\x73\x40\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63" +selfsign+="\x6f\x6d\x82\x09\x00\xe1\xaa\x44\xda\xac\x8f\x12\x04\x30\x0d\x06" +selfsign+="\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01" +selfsign+="\x00\xb6\x43\x7f\xb0\x66\xfd\x00\x99\x0e\x23\x9c\x17\x5e\x11\xe5" +selfsign+="\x1f\x24\x85\xee\x5e\x12\x9b\xa0\xb0\x4f\x24\x8f\xf1\xaf\x78\x01" +selfsign+="\x64\xc4\x32\x0c\x97\xb0\x10\x88\xac\x2c\xf1\xe4\x2c\x51\x0f\x16" +selfsign+="\x6b\xd8\x66\xca\x8e\x63\xda\x41\x36\xec\x75\x3d\x99\xe3\x54\x27" +selfsign+="\xd4\x91\xc7\xcf\x6b\x41\xa8\xa6\xd0\x42\x5e\xe0\x93\xb8\x77\xd2" +selfsign+="\x83\x09\xf7\x56\x1e\x03\xb3\x12\x8f\x22\xa6\x50\xfd\x59\x6e\x22" +selfsign+="\x3f\xc5\xe3\x0b\x76\xb7\x8a\x06\x90\x3a\x91\xdd\x74\x02\x42\x00" +selfsign+="\x21\xb6\x1b\x92\xb9\x34\x84\x36\x89\x2c\xba\xf5\x1c\xa1\xfa\x39" +selfsign+="\x95\x44\x5b\xdc\x44\xaf\x53\x79\x5f\x34\x43\xcc\x91\x01\xce\x8d" +selfsign+="\x6b\x33\xbe\xe3\x25\xaf\xb7\xc6\xa7\x46\x3a\xb5\x94\x37\xcc\xd9" +selfsign+="\xdb\x40\x56\x49\x2f\x4d\x5e\xfb\x7d\xab\x09\xf1\x66\xde\xb6\x67" +selfsign+="\x9f\x80\xc7\xa0\xce\x46\x5a\x10\xb4\xf3\x42\x21\x14\x69\x0c\x4e" +selfsign+="\x25\x6f\xd1\x0a\xc1\x33\x27\xcf\x09\x0e\x10\x83\xb9\x3d\x4f\x0c" +selfsign+="\x2f\x29\x2c\xb3\x19\x37\x3d\x57\x0e\xe3\xbe\x53\x8d\x54\x96\xcd" +selfsign+="\x8f\x6f\x1d\x15\x2b\x28\xfa\x4f\x5c\x0c\x4e\x1d\x9d\xf9\x38\x7a" +selfsign+="\x9d\x44\x3d\x85\x89\xee\x70\xb4\xe6\x73\xe7\x36\x33\x21\xa5\x84" +selfsign+="\x18" + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring for CA keys +marker "ADD CA KEYRING" +create_keyring ca @s +expect_keyid cakeyring + +# create a keyring using the keys in user CA for validation +marker "ADD RESTRICTED USER KEYRING (parent keyring)" +create_keyring rbkr @s +expect_keyid restricted_by_keyring +restrict_keyring $restricted_by_keyring "asymmetric" "key_or_keyring:$cakeyring" + +# verify cycle detection +marker "REJECT RESTRICTION CYCLE" +restrict_keyring --fail $cakeyring "asymmetric" "key_or_keyring:$restricted_by_keyring" + +# confirm that a restricted keyring cannot be restricted again +marker "REJECT REPEATED RESTRICTION" +restrict_keyring --fail $restricted_by_keyring "asymmetric" "builtin_trusted" + +# create a keyring using the keys in builtin CA for validation +marker "ADD RESTRICTED BUILTIN KEYRING" +create_keyring rbb @s +expect_keyid restricted_by_builtin +restrict_keyring $restricted_by_builtin "asymmetric" "builtin_trusted" + +# add CA certificate to CA keyring +marker "ADD USER SIGNED CERT" +pcreate_key "-e $cacert1" asymmetric "" $cakeyring +expect_keyid cacert1id + +# attempt validation of signed key +marker "REJECT KEY SIGNED BY UNKNOWN CA" +pcreate_key --fail "-e $signed" asymmetric "" $restricted_by_keyring + +# attempt validation of signed key +marker "REJECT KEY NOT SIGNED BY BUILTIN" +pcreate_key --fail "-e $signed" asymmetric "" $restricted_by_builtin + +# add another CA certificate to CA keyring +marker "ADD SECOND CA KEY" +pcreate_key "-e $cacert2" asymmetric "" $cakeyring +expect_keyid cacert2id + +# create a keyring restricted on a single key +marker "ADD RESTRICTED USER KEYRING (parent key)" +create_keyring rbk @s +expect_keyid restricted_by_key +restrict_keyring $restricted_by_key "asymmetric" "key_or_keyring:$cacert2id" + +# attempt validation of signed key +marker "ADD KEY SIGNED BY KNOWN CA" +pcreate_key "-e $signed" asymmetric "" $restricted_by_keyring +expect_keyid signedid +link_key $signedid $restricted_by_key + +# confirm that self-signed key cannot be added +marker "REJECT SELF-SIGNED KEY" +pcreate_key --fail "-e $selfsign" asymmetric "" $restricted_by_keyring +pcreate_key --fail "-e $selfsign" asymmetric "" $restricted_by_key + +# confirm that the keyring restriction cannot be changed +marker "REJECT RESTRICTION CHANGE" +restrict_keyring --fail $restricted_by_key "asymmetric" "builtin_trusted" + +# create two self-restricted keyrings +marker "ADD USER KEYRINGS (self)" +create_keyring rbs1 @s +expect_keyid restricted_by_self1 +create_keyring rbs2 @s +expect_keyid restricted_by_self2 + +# add first certificate (treated as root cert) to self-restricted keyrings +marker "ADD FIRST CERT TO SELF-RESTRICTED KEYRINGS" +link_key $signedid $restricted_by_self1 +link_key $cacert2id $restricted_by_self2 + +# apply restrictions +marker "RESTRICT USER KEYRINGS" +restrict_keyring $restricted_by_self1 "asymmetric" "key_or_keyring:0:chain" +restrict_keyring $restricted_by_self2 "asymmetric" "key_or_keyring:0:chain" + +# reject certificate addition to self-restricted keyring +marker "REJECT CERTS FOR SELF-RESTRICTED KEYRING" +link_key --fail $cacert2id $restricted_by_self1 +pcreate_key --fail "-e $selfsign" asymmetric "" $restricted_by_self1 +pcreate_key --fail "-e $selfsign" asymmetric "" $restricted_by_self2 + +# add certificate to self-restricted keyring +marker "ADD CERT TO SELF-RESTRICTED KEYRING" +link_key $signedid $restricted_by_self2 + +# check certificate signed using an intermediate CA +marker "ADD INTERMEDIATE SIGNED CERT TO SELF-RESTRICTED KEYRING" +pcreate_key "-e $intcert" asymmetric "" $restricted_by_self2 +expect_keyid intcertid +pcreate_key "-e $intsigned" asymmetric "" $restricted_by_self2 +expect_keyid intsignedid + +# check intermediate CA with a parent keyring when CA is missing +marker "REJECT INTERMEDIATE SIGNED CERT WITHOUT INTERMEDIATE CA" +create_keyring restricted_by_int @s +expect_keyid restricted_by_int +restrict_keyring $restricted_by_int "asymmetric" "key_or_keyring:$cakeyring:chain" +link_key --fail $intsignedid $restricted_by_int + +# check intermediate CA with a parent keyring and valid CA +marker "ADD INTERMEDIATE SIGNED CERT WITH INTERMEDIATE CA" +link_key $intcertid $restricted_by_int +link_key $intsignedid $restricted_by_int + +# create a fully-restricted keyring (no links allowed) +marker "ADD FULLY-RESTRICTED KEYRING" +create_keyring fr @s +expect_keyid fully_restricted +link_key $cacert2id $fully_restricted +restrict_keyring $fully_restricted + +# reject certificate addition to fully-restricted keyring +marker "REJECT CERTS FOR FULLY-RESTRICTED KEYRING" +link_key --fail $cacert2id $fully_restricted +pcreate_key --fail "-e $selfsign" asymmetric "" $fully_restricted + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/revoke/bad-args/runtest.sh b/tests/keyctl/revoke/bad-args/runtest.sh new file mode 100644 index 0000000000..a6c0082f07 --- /dev/null +++ b/tests/keyctl/revoke/bad-args/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +revoke_key --fail 0 +expect_error EINVAL + +# check that a non-existent key ID fails correctly +marker "CHECK NON-EXISTENT KEY ID" +revoke_key --fail @t +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/revoke/noargs/runtest.sh b/tests/keyctl/revoke/noargs/runtest.sh new file mode 100644 index 0000000000..94e1b7a330 --- /dev/null +++ b/tests/keyctl/revoke/noargs/runtest.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl revoke + +# check that two arguments fail correctly +marker "ADD TWO ARGS" +expect_args_error keyctl revoke 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/revoke/valid/runtest.sh b/tests/keyctl/revoke/valid/runtest.sh new file mode 100644 index 0000000000..55bbbdf159 --- /dev/null +++ b/tests/keyctl/revoke/valid/runtest.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# create a key and attach it to the new keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list the keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist ringlist $keyid + +# check we can read the key description +marker "CHECK VALIDATE KEY" +describe_key $keyid +expect_key_rdesc kdesc 'user@.*@lizard' + +# check we can read the key's payload +marker "CHECK READ PAYLOAD" +print_key $keyid +expect_payload kpayload "gizzard" + +# revoke the key +marker "REVOKE KEY" +revoke_key $keyid + +# check we can no longer read the key description +marker "CHECK NO VALIDATE KEY" +describe_key --fail $keyid +expect_error EKEYREVOKED + +# check we can no longer read the key's payload +marker "CHECK NO READ PAYLOAD" +print_key --fail $keyid +expect_error EKEYREVOKED + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid $keyringid + +# revoke the keyring +marker "REVOKE KEYRING" +revoke_key $keyringid + +# listing the session keyring should fail +marker "CHECK NO LIST SESSION KEYRING" +list_keyring --fail $keyringid +expect_error EKEYREVOKED + +# validating the new keyring's name and type should also fail +marker "CHECK NO VALIDATE KEYRING" +describe_key --fail $keyringid +expect_error EKEYREVOKED + +# remove the keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/search/bad-args/runtest.sh b/tests/keyctl/search/bad-args/runtest.sh new file mode 100644 index 0000000000..dfec8ddc20 --- /dev/null +++ b/tests/keyctl/search/bad-args/runtest.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that an empty key type fails correctly +marker "CHECK EMPTY KEY TYPE" +search_for_key --fail @s "" wibble +expect_error EINVAL +search_for_key --fail @s "" wibble @p +expect_error EINVAL + +# check that an unsupported key type fails correctly +marker "CHECK UNSUPPORTED KEY TYPE" +search_for_key --fail @s lizardsgizzards wibble +expect_error ENOKEY +search_for_key --fail @s lizardsgizzards wibble @p +expect_error ENOKEY + +# check that an invalid key type fails correctly +marker "CHECK INVALID KEY TYPE" +search_for_key --fail @s .user wibble +expect_error EPERM +search_for_key --fail @s .user wibble @p +expect_error EPERM + +# check that an overlong key type fails correctly +marker "CHECK OVERLONG KEY TYPE" +search_for_key --fail @s $maxtype wibble +expect_error ENOKEY +search_for_key --fail @s a$maxtype wibble @p +expect_error EINVAL + +# check that an max length key description works correctly (4095 inc NUL) +marker "CHECK MAXLEN DESC" +search_for_key --fail @s user $maxdesc +expect_error ENOKEY + +search_for_key --fail @s user $maxdesc @p +expect_error ENOKEY + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong key description fails correctly (>4095 inc NUL) + marker "CHECK OVERLONG DESC" + search_for_key --fail @s user a$maxdesc + expect_error EINVAL +fi + +search_for_key --fail @s user a$maxdesc @p +expect_error EINVAL + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +search_for_key --fail @s user wibble -2000 +expect_error EINVAL + +# create a non-keyring key +marker "CREATE KEY" +create_key user a a @s +expect_keyid keyid + +# search the non-keyring key +marker "SEARCH KEY" +search_for_key --fail $keyid user a +expect_error ENOTDIR +search_for_key --fail $keyid user a @p +expect_error ENOTDIR + +# dispose of the key +marker "UNLINK KEY" +unlink_key $keyid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/search/noargs/runtest.sh b/tests/keyctl/search/noargs/runtest.sh new file mode 100644 index 0000000000..912d614ad5 --- /dev/null +++ b/tests/keyctl/search/noargs/runtest.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl search + +# check that one argument fails correctly +marker "ONE ARGS" +expect_args_error keyctl search 0 + +# check that two arguments fails correctly +marker "TWO ARGS" +expect_args_error keyctl search 0 0 + +# check that five arguments fails correctly +marker "FIVE ARGS" +expect_args_error keyctl search 0 0 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/search/valid/runtest.sh b/tests/keyctl/search/valid/runtest.sh new file mode 100644 index 0000000000..fb51b2164a --- /dev/null +++ b/tests/keyctl/search/valid/runtest.sh @@ -0,0 +1,186 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a pair of keyrings and attach them to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +create_keyring wibble2 @s +expect_keyid keyring2id + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# search the session keyring for a non-existent key +marker "SEARCH SESSION FOR NON-EXISTENT KEY" +search_for_key --fail @s user snake +expect_error ENOKEY + +# search the session keyring for the key +marker "SEARCH SESSION" +search_for_key @s user lizard +expect_keyid found $keyid + +# search the session keyring for the key and attach to second keyring +marker "SEARCH SESSION AND ATTACH" +search_for_key @s user lizard $keyring2id +expect_keyid found $keyid + +# check it's attached to the second keyring +marker "CHECK ATTACHED" +list_keyring $keyring2id +expect_keyring_rlist rlist $keyid + +# check the key contains what we expect +marker "CHECK PAYLOAD" +print_key $keyid +expect_payload payload "gizzard" + +# detach the attachment just made +marker "DETACH KEY" +unlink_key $found $keyring2id + +# create an overlapping key in the second keyring +create_key user lizard skin $keyring2id +expect_keyid keyid2 + +# check the two keys contain what we expect +marker "CHECK PAYLOADS" +print_key $keyid +expect_payload payload "gizzard" +print_key $keyid2 +expect_payload payload "skin" + +# a search from the session keyring should find the first key +marker "SEARCH SESSION AGAIN" +search_for_key @s user lizard +expect_keyid found $keyid + +# a search from the first keyring should find the first key +marker "SEARCH FIRST KEYRING" +search_for_key $keyringid user lizard +expect_keyid found $keyid + +# a search from the second keyring should find the second key +marker "SEARCH SECOND KEYRING" +search_for_key $keyring2id user lizard +expect_keyid found $keyid2 + +# link the second keyring to the first +marker "LINK FIRST KEYRING TO SECOND" +link_key $keyring2id $keyringid + +# a search from the first keyring should again find the first key +marker "SEARCH FIRST KEYRING AGAIN" +search_for_key $keyringid user lizard +expect_keyid found $keyid + +# revoking the first key should cause the second key to be available +revoke_key $keyid +search_for_key $keyringid user lizard +expect_keyid found $keyid2 + +# get rid of the dead key +marker "UNLINK FIRST KEY" +unlink_key $keyid $keyringid + +# a search from the first keyring should now find the second key +marker "SEARCH FIRST KEYRING AGAIN 2" +search_for_key $keyringid user lizard +expect_keyid found $keyid2 + +# a search from the session keyring should now find the second key +marker "SEARCH SESSION KEYRING AGAIN 2" +search_for_key @s user lizard +expect_keyid found $keyid2 + +# unlink the second keyring from the first +marker "UNLINK SECOND KEYRING FROM FIRST" +unlink_key $keyring2id $keyringid + +# a search from the first keyring should now fail +marker "SEARCH FIRST KEYRING FOR FAIL" +search_for_key --fail $keyringid user lizard +expect_error ENOKEY + +# a search from the session keyring should still find the second key +marker "SEARCH SESSION KEYRING AGAIN 3" +search_for_key @s user lizard +expect_keyid found $keyid2 + +# move the second keyring into the first +marker "MOVE SECOND KEYRING INTO FIRST" +link_key $keyring2id $keyringid +unlink_key $keyring2id @s + +# a search from the first keyring should now find the second key once again +marker "SEARCH FIRST KEYRING AGAIN 4" +search_for_key $keyringid user lizard +expect_keyid found $keyid2 + +# removing search permission on the second keyring should hide the key +marker "SEARCH WITH NO-SEARCH KEYRING" +set_key_perm $keyring2id 0x370000 +search_for_key --fail $keyringid user lizard +expect_error ENOKEY + +# putting search permission on the second keyring back again should make it +# available again +set_key_perm $keyring2id 0x3f0000 +search_for_key $keyringid user lizard +expect_keyid found $keyid2 + +# removing search permission on the second key should hide the key +marker "SEARCH WITH NO-SEARCH KEYRING2" +set_key_perm $keyring2id 0x370000 +search_for_key --fail $keyringid user lizard +expect_error ENOKEY + +# putting search permission on the second key back again should make it +# available again +set_key_perm $keyring2id 0x3f0000 +search_for_key $keyringid user lizard +expect_keyid found $keyid2 + +# revoking the key should make the key unavailable +revoke_key $keyid2 +search_for_key --fail $keyringid user lizard +kver=`uname -r` +case $kver in + *.el7*) + expect_error EKEYREVOKED + ;; + *) + if kernel_older_than 3.13 + then + expect_error ENOKEY + else + expect_error EKEYREVOKED + fi + ;; +esac + +# remove the keyrings we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/session/bad-args/runtest.sh b/tests/keyctl/session/bad-args/runtest.sh new file mode 100644 index 0000000000..8bae0d46ad --- /dev/null +++ b/tests/keyctl/session/bad-args/runtest.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that an empty keyring name fails correctly +marker "SESSION WITH EMPTY KEYRING NAME" +new_session --fail "" +expect_error EINVAL + +# This doesn't work on MIPS earler than 3.19 because of a kernel bug +kver=`uname -r` +kmch=`uname -m` +if kernel_at_or_later_than 3.19 || + [ "$kmch" != "mips" -a "$kmch" != "mips64" ] +then + # check that an overlong keyring name fails correctly + marker "SESSION WITH OVERLONG KEYRING NAME" + new_session --fail a$maxdesc + expect_error EINVAL +fi + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/session/valid/runtest.sh b/tests/keyctl/session/valid/runtest.sh new file mode 100644 index 0000000000..4c831314c0 --- /dev/null +++ b/tests/keyctl/session/valid/runtest.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# describe the keyring created for an anonymous session +if [ $OSDIST = RHEL ] && version_less_than $OSRELEASE 6 +then + marker "ANON SESSION" + new_session - keyctl rdescribe @s "@" + expect_key_rdesc rdesc "keyring@.*@.*@.*@_ses[^@]*\$" + + # check the session keyring ID is shown + seskeyring="`tail -2 $OUTPUTFILE | head -1`" + if ! expr "$seskeyring" : "Joined session keyring: [0-9]*" >&/dev/null + then + failed + fi +fi + +# describe the keyring created for a named session +marker "NAMED SESSION" +new_session qwerty keyctl rdescribe @s "@" +expect_key_rdesc rdesc "keyring@.*@.*@.*@qwerty" + +# check the session keyring ID is shown +seskeyring="`tail -2 $OUTPUTFILE | head -1`" +if ! expr "$seskeyring" : "Joined session keyring: [0-9]*" >&/dev/null +then + failed +fi + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/show/noargs/runtest.sh b/tests/keyctl/show/noargs/runtest.sh new file mode 100644 index 0000000000..d5072716c7 --- /dev/null +++ b/tests/keyctl/show/noargs/runtest.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that show shows us our session keyring +marker "SHOW SESSION KEYRING" +keyctl show >>$OUTPUTFILE 2>&1 +if [ $? != 0 ] +then + failed +fi + +# must be at least two lines in the output (plus the test banner lines) +nlines=`wc -l $OUTPUTFILE | cut -d\ -f1` +if [ "$nlines" -lt 4 ] +then + failed +fi + +# there must be a session keyring section on the third line +if [ "`sed -n -e 3p $OUTPUTFILE`" != "Session Keyring" ] +then + failed +fi + +# the first key listed (line 2) should be a keying (the session keyring) ... +keyring1="`grep -n keyring $OUTPUTFILE | cut -d: -f1 | head -1`" +if [ "$keyring1" != "4" ] +then + failed +fi + +# ... and it should be the session keyring +keyring1name="`sed -n -e 4p $OUTPUTFILE | awk '{print $6}'`" +if ! expr "$keyring1name" : "^RHTS/keyctl" >&/dev/null +then + failed +fi + + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/show/valid/runtest.sh b/tests/keyctl/show/valid/runtest.sh new file mode 100644 index 0000000000..cbdd85f214 --- /dev/null +++ b/tests/keyctl/show/valid/runtest.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# add some keyrings, nested one inside the other +nr_keyrings=7 +keyrings= +parent=@s +for ((i=1; i<=$nr_keyrings; i++)) +do + marker "ADD KEYRING $i" + create_keyring wibble$i $parent + expect_keyid keyringid + parent=$keyringid + keyrings="$keyrings $keyringid" +done + +# check that show works +marker "SHOW SESSION KEYRING" +keyctl show >>$OUTPUTFILE 2>&1 +if [ $? != 0 ] +then + failed +fi + +if [ $OSDIST = RHEL ] && ! version_less_than $OSRELEASE 6.6 || + keyutils_at_or_later_than 1.5.6 +then + # should be eight lines in the output (banner + session + 6 keyrings) + marker "COUNT LINES" + nlines=`keyctl show | wc -l` + if [ "$nlines" -ne $(($nr_keyrings + 2)) ] + then + failed + fi + + # check the key ID list + marker "CHECK KEY ID LIST" + keyids=`keyctl show | tail -n +3 | cut -c1-11` + + # we need to fix up the whitespace + keyids=`echo $keyids` + keyrings=`echo $keyrings` + + echo "Compare '$keyids'" >>$OUTPUTFILE + echo "And '$keyrings'" >>$OUTPUTFILE + if [ "$keyids" != "$keyrings" ] + then + failed + fi +fi + +# check that shows of specified keyrings also work +if keyutils_at_or_later_than 1.5.4 +then + declare -i j + j=$nr_keyrings + for i in $keyrings + do + marker "CHECK SHOW OTHERS $j" + echo --- $i >>$OUTPUTFILE + if ! keyctl show $i >>$OUTPUTFILE + then + failed + fi + k=`keyctl show $i | wc -l` + if [ $(($j + 1)) != $k ] + then + failed + fi + j=$(($j - 1)) + done +fi +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/supports/bad-args/runtest.sh b/tests/keyctl/supports/bad-args/runtest.sh new file mode 100644 index 0000000000..05581a477f --- /dev/null +++ b/tests/keyctl/supports/bad-args/runtest.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that two arguments fails correctly +marker "TWO ARGS" +expect_args_error keyctl support 0 0 + +# check that three arguments fails correctly +marker "THREE ARGS" +expect_args_error keyctl support 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/supports/valid/runtest.sh b/tests/keyctl/supports/valid/runtest.sh new file mode 100644 index 0000000000..2c62ef2cb5 --- /dev/null +++ b/tests/keyctl/supports/valid/runtest.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# Check that listing caps works +marker "LIST CAPS" +supports + +# check that querying a cap works +marker "QUERY CAP" +supports --unrecognised xxx + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/timeout/bad-args/runtest.sh b/tests/keyctl/timeout/bad-args/runtest.sh new file mode 100644 index 0000000000..a93cd2d7e5 --- /dev/null +++ b/tests/keyctl/timeout/bad-args/runtest.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK BAD KEY ID" +timeout_key --fail 0 10 +expect_error EINVAL + +# get a key +marker "CREATE KEY" +create_key user a a @s +expect_keyid keyid + +# dispose of the key so we can use its ID +marker "DESTROY KEY ID" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK NON-EXISTENT KEY ID" +timeout_key --fail $keyid 10 +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/timeout/noargs/runtest.sh b/tests/keyctl/timeout/noargs/runtest.sh new file mode 100644 index 0000000000..a2e730f474 --- /dev/null +++ b/tests/keyctl/timeout/noargs/runtest.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl timeout + +# check that one argument fails correctly +marker "ADD ONE ARG" +expect_args_error keyctl timeout 0 + +# check that three arguments fail correctly +marker "ADD THREE ARGS" +expect_args_error keyctl timeout 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/timeout/valid/runtest.sh b/tests/keyctl/timeout/valid/runtest.sh new file mode 100644 index 0000000000..4d772bbf84 --- /dev/null +++ b/tests/keyctl/timeout/valid/runtest.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# create a key and attach it to the new keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list the keyring +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist ringlist $keyid + +# check we can read the key description +marker "CHECK VALIDATE KEY" +describe_key $keyid +expect_key_rdesc kdesc 'user@.*@lizard' + +# check we can read the key's payload +marker "CHECK READ PAYLOAD" +print_key $keyid +expect_payload kpayload "gizzard" + +# set a silly timeout on the key +marker "SET BIG TIMEOUT" +timeout_key $keyid 10000000 + +# check we can still read the key's payload +marker "CHECK READ PAYLOAD 2" +print_key $keyid +expect_payload kpayload "gizzard" + +# set a small timeout on the key +marker "SET SMALL TIMEOUT" +timeout_key $keyid 2 + +marker "WAIT FOR TIMEOUT" +sleep_at_least 2 + +# check the key has expired +marker "CHECK NO READ PAYLOAD" +print_key --fail $keyid +if kernel_at_or_later_than 3.8 && kernel_older_than 3.13 && + ! rhel7_kernel_at_or_later_than 3.10.0-42.el7 +then + expect_error ENOKEY +else + expect_error EKEYEXPIRED +fi + +# check revocation doesn't work +marker "CHECK NO REVOKE KEY" +revoke_key --fail $keyid +expect_error EKEYEXPIRED + +# check timeout setting doesn't work +marker "CHECK NO TIMEOUT KEY" +timeout_key --fail $keyid 20 +expect_error EKEYEXPIRED + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid $keyringid + +############################################################################### +# create a key and attach it to the new keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# set a silly timeout on the key +marker "SET BIG TIMEOUT" +timeout_key $keyid 10000000 + +# revoke the key +marker "REVOKE KEY" +revoke_key $keyid + +# check we can no longer set the key's timeout +marker "CHECK NO SET KEY TIMEOUT" +timeout_key --fail $keyid 20 +expect_error EKEYREVOKED + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid $keyringid + +# revoke the keyring +marker "TIMEOUT KEYRING" +timeout_key $keyringid 1 + +marker "WAIT FOR KEYRING TIMEOUT" +sleep_at_least 1 + +# listing the session keyring should fail +marker "CHECK NO LIST SESSION KEYRING" +list_keyring --fail $keyringid +if kernel_at_or_later_than 3.8 && kernel_older_than 3.13 && + ! rhel7_kernel_at_or_later_than 3.10.0-42.el7 +then + expect_error ENOKEY +else + expect_error EKEYEXPIRED +fi + +# validating the new keyring's name and type should also fail +marker "CHECK NO VALIDATE KEYRING" +describe_key --fail $keyringid +expect_error EKEYEXPIRED + +# remove the keyring we added +marker "UNLINK KEYRING" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/unlink/all/runtest.sh b/tests/keyctl/unlink/all/runtest.sh new file mode 100644 index 0000000000..24aaa3f60d --- /dev/null +++ b/tests/keyctl/unlink/all/runtest.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS + +if keyutils_at_or_later_than 1.5 +then + echo "++++ BEGINNING TEST" >$OUTPUTFILE + + # create a keyring and attach it to the session keyring + marker "ADD KEYRING" + create_keyring wibble @s + expect_keyid keyringid + + # stick a key in the keyring + marker "ADD KEY" + create_key user lizard gizzard $keyringid + expect_keyid keyid + + # check that we can list it + marker "LIST KEYRING WITH ONE" + list_keyring $keyringid + expect_keyring_rlist rlist $keyid + + # dispose of the key and make sure it gets destroyed + marker "UNLINK KEY FROM KEYRING" + unlink_key --wait $keyid $keyringid + + # trying a tree-wide unlink should succeed with no links removed + marker "CHECK NO UNLINK KEY FROM TREE" + unlink_key $keyid + expect_unlink_count n_unlinked 0 + + # check that the keyring is now empty + marker "LIST KEYRING" + list_keyring $keyringid + expect_keyring_rlist rlist empty + + # create a key to be massively linked + marker "ADD MULTI KEY" + create_key user lizard gizzard $keyringid + expect_keyid keyid + + # stick twenty keyrings in the keyring with twenty links + marker "ADD TWENTY KEYRINGS WITH LINKS" + subrings= + for ((i=0; i<20; i++)) + do + create_keyring ring$i $keyringid + expect_keyid x + keys="$keys $x" + subrings="$subrings $x" + list_keyring $keyringid + expect_keyring_rlist rlist $x + + link_key $keyid $x + list_keyring $x + expect_keyring_rlist rlist $keyid + done + + marker "SHOW" + if ! keyctl show >>$OUTPUTFILE 2>&1 + then + failed + fi + + # delete all the keys from the keyring tree + marker "REMOVE ALL LINKS TO KEY" + unlink_key $keyid + expect_unlink_count n_unlinked 21 + + # there should not now be any left + unlink_key $keyid + expect_unlink_count n_unlinked 0 + + # check that the key is no longer in the main keyring + marker "CHECK GONE" + list_keyring $keyringid + expect_keyring_rlist rlist $keyid --absent + + for i in $subrings + do + list_keyring $i + expect_keyring_rlist rlist $keyid --absent + done + + # remove the keyring we added + marker "UNLINK KEY" + unlink_key $keyringid @s + + echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE +else + toolbox_skip_test $TEST "SKIPPING TEST DUE TO LACK OF UNLINK-ALL" + exit 0 +fi + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/unlink/bad-args/runtest.sh b/tests/keyctl/unlink/bad-args/runtest.sh new file mode 100644 index 0000000000..67cc498f94 --- /dev/null +++ b/tests/keyctl/unlink/bad-args/runtest.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that a bad key ID fails correctly +marker "CHECK UNLINK BAD KEY ID" +unlink_key --fail 0 @s +expect_error EINVAL + +marker "CHECK UNLINK FROM BAD KEY ID" +unlink_key --fail @s 0 +expect_error EINVAL + +# create a non-keyring +marker "CREATE KEY" +create_key user lizard gizzard @s +expect_keyid keyid + +# check that unlinking from a non-keyring ID fails correctly +marker "CHECK UNLINK FROM NON-KEYRING KEY" +unlink_key --fail @s $keyid +expect_error ENOTDIR + +# dispose of the key we were using +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# check that a non-existent key ID fails correctly +marker "CHECK UNLINK FROM NON-EXISTENT KEY ID" +unlink_key --fail @s $keyid +expect_error ENOKEY + +marker "CHECK UNLINK NON-EXISTENT KEY ID" +unlink_key --fail $keyid @s +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/unlink/noargs/runtest.sh b/tests/keyctl/unlink/noargs/runtest.sh new file mode 100644 index 0000000000..e1baf1f961 --- /dev/null +++ b/tests/keyctl/unlink/noargs/runtest.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "NO ARGS" +expect_args_error keyctl unlink + +if keyutils_older_than 1.5 +then + # check that one argument fails correctly + marker "ONE ARGS" + expect_args_error keyctl unlink 0 +fi + +# check that three arguments fails correctly +marker "THREE ARGS" +expect_args_error keyctl unlink 0 0 0 + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/unlink/valid/runtest.sh b/tests/keyctl/unlink/valid/runtest.sh new file mode 100644 index 0000000000..9b9fa2ee53 --- /dev/null +++ b/tests/keyctl/unlink/valid/runtest.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# create a keyring and attach it to the session keyring +marker "ADD KEYRING" +create_keyring wibble @s +expect_keyid keyringid + +# stick a key in the keyring +marker "ADD KEY" +create_key user lizard gizzard $keyringid +expect_keyid keyid + +# check that we can list it +marker "LIST KEYRING WITH ONE" +list_keyring $keyringid +expect_keyring_rlist rlist $keyid + +# dispose of the key and make sure it gets destroyed +marker "UNLINK KEY FROM KEYRING" +unlink_key --wait $keyid $keyringid + +# trying again should fail +marker "CHECK NO UNLINK KEY FROM KEYRING" +unlink_key --fail $keyid $keyringid +expect_error ENOKEY + +# check that the keyring is now empty +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# stick twenty keys and twenty keyrings in the keyring +marker "ADD TWENTY KEYS" +keys="" +for ((i=0; i<20; i++)) + do + create_key user lizard$i gizzard$i $keyringid + expect_keyid x + keys="$keys $x" + list_keyring $keyringid + expect_keyring_rlist rlist $x +done + +marker "ADD TWENTY KEYRINGS" +for ((i=0; i<20; i++)) + do + create_keyring ring$i $keyringid + expect_keyid x + keys="$keys $x" + list_keyring $keyringid + expect_keyring_rlist rlist $x +done + +marker "CHECK KEYRING CONTENTS" +list_keyring $keyringid +for i in $keys +do + expect_keyring_rlist rlist $i +done + +marker "SHOW" +if ! keyctl show >>$OUTPUTFILE 2>&1 +then + failed +fi + +# delete all the keys from the keyring +marker "DELETE CONTENTS OF KEYRING" +for i in $keys + do + unlink_key --wait $i $keyringid + unlink_key --fail $i $keyringid + expect_error ENOKEY +done + +keyctl show + +# check that it's now empty +marker "LIST KEYRING" +list_keyring $keyringid +expect_keyring_rlist rlist empty + +# remove the keyring we added +marker "UNLINK KEY" +unlink_key $keyringid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/update/bad-args/runtest.sh b/tests/keyctl/update/bad-args/runtest.sh new file mode 100644 index 0000000000..14e7a19b61 --- /dev/null +++ b/tests/keyctl/update/bad-args/runtest.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# attempt to update the session keyring +marker "CHECK UPDATE SESSION KEYRING" +update_key --fail @s a +expect_error EOPNOTSUPP + +# attempt to update an invalid key +marker "CHECK UPDATE INVALID KEY" +update_key --fail 0 a +expect_error EINVAL + +# add a user key to the session keyring for us to play with +marker "ADD USER KEY" +create_key user wibble stuff @s +expect_keyid keyid + +# remove the key we just added +marker "UNLINK KEY" +unlink_key --wait $keyid @s + +# it should fail when we attempt to update it +marker "UPDATE UNLINKED KEY" +update_key --fail $keyid @s +expect_error ENOKEY + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/update/noargs/runtest.sh b/tests/keyctl/update/noargs/runtest.sh new file mode 100644 index 0000000000..8e570b9237 --- /dev/null +++ b/tests/keyctl/update/noargs/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that no arguments fails correctly +marker "ADD NO ARGS" +expect_args_error keyctl update + +# check that one argument fails correctly +marker "ADD ONE ARG" +expect_args_error keyctl update user + +# check that three arguments fail correctly +marker "ADD THREE ARGS" +expect_args_error keyctl update user wibble stuff + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/keyctl/update/userupdate/runtest.sh b/tests/keyctl/update/userupdate/runtest.sh new file mode 100644 index 0000000000..ddc7cd4ccc --- /dev/null +++ b/tests/keyctl/update/userupdate/runtest.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +. ../../../prepare.inc.sh +. ../../../toolbox.inc.sh + + +# ---- do the actual testing ---- + +result=PASS +echo "++++ BEGINNING TEST" >$OUTPUTFILE + +# check that we can add a user key to the session keyring +marker "ADD USER KEY" +create_key user wibble stuff @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + +# check that we can update a user key +marker "UPDATE USER KEY" +update_key $keyid "lizard" + +# read back what we changed it to +marker "PRINT UPDATED PAYLOAD" +print_key $keyid +expect_payload payload "lizard" + +# remove the key we added +marker "UNLINK KEY" +unlink_key $keyid @s + +echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE + +# --- then report the results in the database --- +toolbox_report_result $TEST $result diff --git a/tests/prepare.inc.sh b/tests/prepare.inc.sh new file mode 100644 index 0000000000..448e42becb --- /dev/null +++ b/tests/prepare.inc.sh @@ -0,0 +1,138 @@ +# preparation script for running keyring tests + +# Find the relative path from pwd to the directory holding this file +includes=${BASH_SOURCE[0]} +includes=${includes%/*}/ + +# --- need to run in own session keyring +if [ "x`keyctl rdescribe @s | sed 's/.*;//'`" != "xRHTS/keyctl/$$" ] +then + echo "Running with session keyring RHTS/keyctl/$$" + exec keyctl session "RHTS/keyctl/$$" bash $0 $@ || exit 8 +fi + +# Set up for the Red Hat Test System +RUNNING_UNDER_RHTS=0 +if [ -x /usr/bin/rhts_environment.sh ] +then + PACKAGE=$(rpm -q --qf "%{name}" --whatprovides /bin/keyctl) + . /usr/bin/rhts_environment.sh + RUNNING_UNDER_RHTS=1 +elif [ -z "$OUTPUTFILE" ] +then + OUTPUTFILE=$PWD/test.out + echo -n >$OUTPUTFILE +fi + +case `lsb_release -i -s` in + Fedora*) OSDIST=Fedora;; + RedHatEnterprise*) OSDIST=RHEL;; + *) OSDIST=Unknown;; +esac + +OSRELEASE=`lsb_release -r -s` + +KEYUTILSVER=`keyctl --version 2>/dev/null` +if [ -n "$KEYUTILSVER" ] +then + : +elif [ -x /bin/rpm ] +then + KEYUTILSVER=`rpm -q keyutils` +else + echo "Can't determine keyutils version" >&2 + exit 9 +fi + +echo "keyutils version: $KEYUTILSVER" +KEYUTILSVER=`expr "$KEYUTILSVER" : '.*keyutils-\([0-9.]*\).*'` + +. $includes/version.inc.sh + +KERNELVER=`uname -r` + +# +# Make sure the TEST envvar is set. +# +if [ -z "$TEST" ] +then + p=`pwd` + case $p in + */keyctl/*) + TEST=keyctl/${p#*/keyctl/} + ;; + */bugzillas/*) + TEST=bugzillas/${p#*/bugzillas/} + ;; + *) + TEST=unknown + ;; + esac +fi + +have_key_invalidate=0 +have_big_key_type=0 +have_dh_compute=0 +have_restrict_keyring=0 + +if keyctl supports capabilities >&/dev/null +then + eval `keyctl supports` +else + # + # Work out whether key invalidation is supported by the kernel + # + if keyutils_at_or_later_than 1.5.6 && kernel_at_or_later_than 3.5-rc1 + then + have_key_invalidate=1 + fi + + # + # Work out whether the big_key type is supported by the kernel. + # + if [ $OSDIST = RHEL ] && ! version_less_than $OSRELEASE 7 + then + # big_key is backported to 3.10 for RHEL-7 + have_big_key_type=1 + elif kernel_at_or_later_than 3.13-rc1 + then + have_big_key_type=1 + fi + + # + # Work out whether Diffie-Hellman is supported by the kernel + # + if [ $OSDIST = RHEL ] + then + : + elif keyutils_at_or_later_than 1.5.10 && kernel_at_or_later_than 4.7-rc1 + then + have_dh_compute=1 + fi + + # + # Work out whether keyring restrictions are supported by the kernel + # + if keyutils_at_or_later_than 1.6 && kernel_at_or_later_than 4.12-rc1 + then + have_restrict_keyring=1 + fi +fi + +# +# Check if skipping of tests requiring root was requested +# +skip_root_required=0 +if [ "$SKIPROOTREQ" = "yes" ] +then + skip_root_required=1 +fi + +# +# Check if skipping of tests requiring installation was requested +# +skip_install_required=0 +if [ "$SKIPINSTALLREQ" = "yes" ] +then + skip_install_required=1 +fi diff --git a/tests/runtest.sh b/tests/runtest.sh new file mode 100644 index 0000000000..b6eaa7c690 --- /dev/null +++ b/tests/runtest.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# set the $AUTOMATED environment variable to non-zero for automated mode +# automated mode will run all the tests to completion +# non-automated mode (default) stops running the test suite on the first error +AUTOMATED=${AUTOMATED:-0} + +TESTS=$* + +PARENTTEST=${TEST} + +if [ `id -u` != 0 ] +then + echo "#### Some tests require root privileges." >&2 + echo "#### It is recommended that this be run as root." >&2 +fi + +for i in ${TESTS}; do + export TEST=$i + pushd $i >/dev/null + echo "### RUNNING TEST $i" + if [[ $AUTOMATED != 0 ]] ; then + bash ./runtest.sh + else + bash ./runtest.sh || exit 1 + fi + popd >/dev/null +done + +if [ `id -u` != 0 ] +then + echo "#### Some tests required root privileges." >&2 + echo "#### They have been tested for the appropriate failure." >&2 + echo "#### It is recommended that this be run as root." >&2 +fi diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh new file mode 100644 index 0000000000..e7b9635fd2 --- /dev/null +++ b/tests/toolbox.inc.sh @@ -0,0 +1,1261 @@ +############################################################################### +# +# Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# +############################################################################### + +echo === $OUTPUTFILE === + +endian=`file -L /proc/$$/exe` +if expr "$endian" : '.* MSB \+\(executable\|shared object\).*' >&/dev/null +then + endian=BE +elif expr "$endian" : '.* LSB \+\(executable\|shared object\).*' >&/dev/null +then + endian=LE +else + echo -e "+++ \e[31;1mCan't Determine Endianness\e[0m" + echo "+++ Can't Determine Endianness" >>$OUTPUTFILE + exit 2 +fi + +maxtypelen=31 +maxtype=`for ((i=0; i<$((maxtypelen)); i++)); do echo -n a; done` + +PAGE_SIZE=`getconf PAGESIZE` +pagelen=$((PAGE_SIZE - 1)) +fullpage=`for ((i=0; i<$((pagelen)); i++)); do echo -n a; done` +string4095=`for ((i=0; i<4095; i++)); do echo -n a; done` + +if kernel_at_or_later_than 3.18 +then + maxdesc=$string4095 +elif rhel6_kernel_at_or_later_than 2.6.32-589.el6 +then + maxdesc=$string4095 +else + maxdesc=$fullpage +fi + +maxcall=$fullpage + +maxsquota=`grep '^ *0': /proc/key-users | sed s@.*/@@` + +key_gc_delay_file="/proc/sys/kernel/keys/gc_delay" +if [ -f $key_gc_delay_file ]; then + orig_gc_delay=`cat $key_gc_delay_file` +else + orig_gc_delay=300 +fi + + +function marker () +{ + echo -e "+++ \e[33m$*\e[0m" + echo +++ $* >>$OUTPUTFILE +} + +function failed() +{ + echo -e "\e[31;1mFAILED\e[0m" + echo === FAILED === >>$OUTPUTFILE + keyctl show >>$OUTPUTFILE + echo ============== >>$OUTPUTFILE + result=FAIL +} + +function expect_args_error () +{ + "$@" >>$OUTPUTFILE 2>&1 + if [ $? != 2 ] + then + failed + fi + +} + +function toolbox_report_result() +{ + if [ $RUNNING_UNDER_RHTS = 1 ] + then + report_result $1 $2 + fi + if [ $2 = FAIL ] + then + exit 1 + fi +} + +function toolbox_skip_test() +{ + echo "++++ SKIPPING TEST" >>$OUTPUTFILE + marker "$2" + toolbox_report_result $1 PASS +} + +############################################################################### +# +# Return true if the command is found in $PATH. If not, log that the test is +# being skipped, report the result as PASS, and exit. +# +############################################################################### +function require_command () +{ + which "$1" >&/dev/null + if [ $? != 0 ] + then + toolbox_skip_test "SKIP DUE TO MISSING COMMAND: $1" + exit 0 + fi +} + +function require_selinux () +{ + if ! grep -q selinuxfs /proc/mounts; + then + toolbox_skip_test $TEST "SKIP DUE TO DISABLED SELINUX" + exit 0 + fi +} + +############################################################################### +# +# extract an error message from the log file and check it +# +############################################################################### +function expect_error () +{ + my_varname=$1 + + my_errmsg="`tail -1 $OUTPUTFILE`" + eval $my_varname="\"$my_errmsg\"" + + if [ $# != 1 ] + then + echo "Format: expect_error " >>$OUTPUTFILE + failed + fi + + case $1 in + EPERM) my_err="Operation not permitted";; + EAGAIN) my_err="Resource temporarily unavailable";; + ENOENT) my_err="No such file or directory";; + EEXIST) my_err="File exists";; + ENOTDIR) my_err="Not a directory";; + EACCES) my_err="Permission denied";; + EINVAL) my_err="Invalid argument";; + ENODEV) my_err="No such device";; + ELOOP) my_err="Too many levels of symbolic links";; + EOPNOTSUPP) my_err="Operation not supported";; + EDEADLK) my_err="Resource deadlock avoided";; + EDQUOT) my_err="Disk quota exceeded";; + ENOKEY) + my_err="Required key not available" + old_err="Requested key not available" + alt_err="Unknown error 126" + ;; + EKEYEXPIRED) + my_err="Key has expired" + alt_err="Unknown error 127" + ;; + EKEYREVOKED) + my_err="Key has been revoked" + alt_err="Unknown error 128" + ;; + EKEYREJECTED) + my_err="Key has been rejected" + alt_err="Unknown error 129" + ;; + *) + echo "Unknown error message $1" >>$OUTPUTFILE + failed + ;; + esac + + if expr "$my_errmsg" : ".*: $my_err" >&/dev/null + then + : + elif [ "x$alt_err" != "x" ] && expr "$my_errmsg" : ".*: $alt_err" >&/dev/null + then + : + elif [ "x$old_err" != "x" ] && expr "$my_errmsg" : ".*: $old_err" >&/dev/null + then + : + else + failed + fi +} + +############################################################################### +# +# wait for a key to be destroyed (get removed from /proc/keys) +# +############################################################################### +function pause_till_key_destroyed () +{ + echo "+++ WAITING FOR KEY TO BE DESTROYED" >>$OUTPUTFILE + hexkeyid=`printf %08x $1` + + while grep $hexkeyid /proc/keys + do + sleep 1 + done +} + +############################################################################### +# +# wait for a key to be unlinked +# +############################################################################### +function pause_till_key_unlinked () +{ + echo "+++ WAITING FOR KEY TO BE UNLINKED" >>$OUTPUTFILE + + while true + do + echo keyctl unlink $1 $2 >>$OUTPUTFILE + keyctl unlink $1 $2 >>$OUTPUTFILE 2>&1 + if [ $? != 1 ] + then + failed + fi + + my_errmsg="`tail -1 $OUTPUTFILE`" + if ! expr "$my_errmsg" : ".*: No such file or directory" >&/dev/null + then + break + fi + sleep 1 + done +} + +############################################################################### +# +# request a key and attach it to the new keyring +# +############################################################################### +function request_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl request "$@" >>$OUTPUTFILE + keyctl request "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# request a key and attach it to the new keyring, calling out if necessary +# +############################################################################### +function request_key_callout () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl request2 "$@" >>$OUTPUTFILE + keyctl request2 "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# request a key and attach it to the new keyring, calling out if necessary and +# passing the callout data in on stdin +# +############################################################################### +function prequest_key_callout () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + data="$1" + shift + + echo echo -n $data \| keyctl prequest2 "$@" >>$OUTPUTFILE + echo -n $data | keyctl prequest2 "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# create a key and attach it to the new keyring +# +############################################################################### +function create_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl add "$@" >>$OUTPUTFILE + keyctl add "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# create a key and attach it to the new keyring, piping in the data +# +############################################################################### +function pcreate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + data="$1" + shift + + echo echo -n $data \| keyctl padd "$@" >>$OUTPUTFILE + echo -n $data | keyctl padd "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# create a key and attach it to the new keyring, piping in the data +# +############################################################################### +function pcreate_key_by_size () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + data="$1" + shift + + echo dd if=/dev/zero count=1 bs=$data \| keyctl padd "$@" >>$OUTPUTFILE + dd if=/dev/zero count=1 bs=$data 2>/dev/null | keyctl padd "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# create a key and attach it to the new keyring +# +############################################################################### +function create_keyring () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl newring "$@" >>$OUTPUTFILE + keyctl newring "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# extract a key ID from the log file +# +############################################################################### +function expect_keyid () +{ + my_varname=$1 + + my_keyid="`tail -1 $OUTPUTFILE`" + if expr "$my_keyid" : '[1-9][0-9]*' >&/dev/null + then + eval $my_varname=$my_keyid + + if [ $# = 2 -a "x$my_keyid" != "x$2" ] + then + failed + fi + else + eval $my_varname=no + result=FAIL + fi +} + +############################################################################### +# +# prettily list a keyring +# +############################################################################### +function pretty_list_keyring () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl list $1 >>$OUTPUTFILE + keyctl list $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# list a keyring +# +############################################################################### +function list_keyring () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl rlist $1 >>$OUTPUTFILE + keyctl rlist $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# extract a keyring listing from the log file and see if a key ID is contained +# therein +# +############################################################################### +function expect_keyring_rlist () +{ + my_varname=$1 + + my_rlist="`tail -1 $OUTPUTFILE`" + eval $my_varname="\"$my_rlist\"" + + if [ $# = 2 -o $# = 3 ] + then + if [ "$2" = "empty" ] + then + if [ "x$my_rlist" != "x" ] + then + failed + fi + else + my_keyid=$2 + my_found=0 + my_expected=1 + if [ $# = 3 -a "x$3" = "x--absent" ]; then my_expected=0; fi + + for k in $my_rlist + do + if [ $k = $my_keyid ] + then + my_found=1 + break; + fi + done + + if [ $my_found != $my_expected ] + then + failed + fi + fi + fi +} + +############################################################################### +# +# prettily describe a key +# +############################################################################### +function pretty_describe_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl describe $1 >>$OUTPUTFILE + keyctl describe $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# describe a key +# +############################################################################### +function describe_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl rdescribe $1 "@" >>$OUTPUTFILE + keyctl rdescribe $1 "@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# extract a raw key description from the log file and check it +# +############################################################################### +function expect_key_rdesc () +{ + my_varname=$1 + + my_rdesc="`tail -1 $OUTPUTFILE`" + eval $my_varname="\"$my_rdesc\"" + + if ! expr "$my_rdesc" : "$2" >&/dev/null + then + failed + fi +} + +############################################################################### +# +# read a key's payload as a hex dump +# +############################################################################### +function read_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl read $1 >>$OUTPUTFILE + keyctl read $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# read a key's payload as a printable string +# +############################################################################### +function print_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl print $1 >>$OUTPUTFILE + keyctl print $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# pipe a key's raw payload to stdout +# +############################################################################### +function pipe_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl pipe $1 >>$OUTPUTFILE + keyctl pipe $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# pipe a key's raw payload through md5sum +# +############################################################################### +function md5sum_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl pipe $1 \| md5sum \| cut -c1-32 >>$OUTPUTFILE + keyctl pipe $1 | md5sum | cut -c1-32 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# extract a printed payload from the log file +# +############################################################################### +function expect_payload () +{ + my_varname=$1 + + my_payload="`tail -1 $OUTPUTFILE`" + eval $my_varname="\"$my_payload\"" + + if [ $# == 2 -a "x$my_payload" != "x$2" ] + then + failed + fi +} + +############################################################################### +# +# extract multiline output from the log file +# +############################################################################### +function expect_multiline () +{ + my_varname=$1 + my_linecount="`echo \"$2\" | wc -l`" + + my_payload=$(tail -$my_linecount $OUTPUTFILE) + eval $my_varname="\"$my_payload\"" + + if [ $# != 2 -o "x$my_payload" != "x$2" ] + then + failed + fi +} + +############################################################################### +# +# revoke a key +# +############################################################################### +function revoke_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl revoke $1 >>$OUTPUTFILE + keyctl revoke $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# unlink a key from a keyring +# +############################################################################### +function unlink_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + my_wait=0 + if [ "x$1" = "x--wait" ] + then + my_wait=1 + shift + fi + + echo keyctl unlink $1 $2 >>$OUTPUTFILE + keyctl unlink $1 $2 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi + + # keys are destroyed lazily + if [ $my_wait = 1 ] + then + pause_till_key_unlinked $1 $2 + fi +} + +############################################################################### +# +# extract a message about the number of keys unlinked +# +############################################################################### +function expect_unlink_count () +{ + my_varname=$1 + + my_nunlinks="`tail -1 $OUTPUTFILE`" + + if ! expr "$my_nunlinks" : '^[0-9][0-9]* links removed$' + then + failed + fi + + my_nunlinks=`echo $my_nunlinks | awk '{printf $1}'` + eval $my_varname="\"$my_nunlinks\"" + + if [ $# == 2 -a $my_nunlinks != $2 ] + then + failed + fi +} + +############################################################################### +# +# update a key from a keyring +# +############################################################################### +function update_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl update $1 $2 >>$OUTPUTFILE + keyctl update $1 $2 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# update a key from a keyring, piping the data in over stdin +# +############################################################################### +function pupdate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo echo -n $2 \| keyctl pupdate $1 >>$OUTPUTFILE + echo -n $2 | keyctl pupdate $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# clear a keyring +# +############################################################################### +function clear_keyring () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl clear $1 >>$OUTPUTFILE + keyctl clear $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# restrict a keyring +# +############################################################################### +function restrict_keyring () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl restrict_keyring $1 $2 $3 >>$OUTPUTFILE + keyctl restrict_keyring $1 $2 $3 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# link a key to a keyring +# +############################################################################### +function link_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl link $1 $2 >>$OUTPUTFILE + keyctl link $1 $2 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# search for a key in a keyring +# +############################################################################### +function search_for_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl search "$@" >>$OUTPUTFILE + keyctl search "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# set the permissions mask on a key +# +############################################################################### +function set_key_perm () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl setperm "$@" >>$OUTPUTFILE + keyctl setperm "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# set the ownership of a key +# +############################################################################### +function chown_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl chown "$@" >>$OUTPUTFILE + keyctl chown "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# set the group ownership of a key +# +############################################################################### +function chgrp_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl chgrp "$@" >>$OUTPUTFILE + keyctl chgrp "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# run as a new session +# +############################################################################### +function new_session () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl session "$@" >>$OUTPUTFILE + keyctl session "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# instantiate a key +# +############################################################################### +function instantiate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl instantiate "$@" >>$OUTPUTFILE + keyctl instantiate "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# instantiate a key, piping the data in over stdin +# +############################################################################### +function pinstantiate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + data="$1" + shift + + echo echo -n $data \| keyctl pinstantiate "$@" >>$OUTPUTFILE + echo -n $data | keyctl pinstantiate "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# negate a key +# +############################################################################### +function negate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl negate "$@" >>$OUTPUTFILE + keyctl negate "$@" >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# set a key's expiry time +# +############################################################################### +function timeout_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl timeout $1 $2 >>$OUTPUTFILE + keyctl timeout $1 $2 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Invalidate a key +# +############################################################################### +function invalidate_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl invalidate $1 >>$OUTPUTFILE + keyctl invalidate $1 >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Do a DH computation +# +############################################################################### +function dh_compute () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl dh_compute $@ >>$OUTPUTFILE + keyctl dh_compute $@ >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Do a DH computation post-processed by a KDF +# +############################################################################### +function dh_compute_kdf () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl dh_compute_kdf $@ >>$OUTPUTFILE + keyctl dh_compute_kdf $@ >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Do a DH computation post-processed by a KDF with other information +# +############################################################################### +function dh_compute_kdf_oi () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl dh_compute_kdf_oi $@ >>$OUTPUTFILE + keyctl dh_compute_kdf_oi $@ >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Move a key between keyrings +# +############################################################################### +function move_key () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + fi + + echo keyctl move $* >>$OUTPUTFILE + keyctl move $* >>$OUTPUTFILE 2>&1 + if [ $? != $my_exitval ] + then + failed + fi +} + +############################################################################### +# +# Query supported features +# +############################################################################### +function supports () +{ + my_exitval=0 + if [ "x$1" = "x--fail" ] + then + my_exitval=1 + shift + elif [ "x$1" = "x--unrecognised" ] + then + my_exitval=3 + shift + fi + + echo keyctl supports $* >>$OUTPUTFILE + keyctl supports $* >>$OUTPUTFILE 2>&1 + err=$? + if [ $err != $my_exitval ] + then + echo exitcode=$err >>$OUTPUTFILE + failed + fi +} + +############################################################################### +# +# Make sure we sleep at least N seconds +# +############################################################################### +function sleep_at_least () +{ + my_now=`date +%s` + my_done_at=$(($my_now+$1+1)) + sleep $1 + while [ `date +%s` -lt $my_done_at ] + do + # Sleep in 1/50th of a second bursts till the time catches up + sleep .02 + done +} + +############################################################################### +# +# set gc delay time, return original value +# +############################################################################### +function set_gc_delay() +{ + delay=$1 + if [ -f $key_gc_delay_file ]; then + echo $delay > $key_gc_delay_file + echo "Set $key_gc_delay_file to $delay, orig: $orig_gc_delay" + fi +} diff --git a/tests/vercmp.sh b/tests/vercmp.sh new file mode 100644 index 0000000000..8310c01d47 --- /dev/null +++ b/tests/vercmp.sh @@ -0,0 +1,31 @@ +# Commandline-driver tester for version comparison shell functions +# +############################################################################### +# +# Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# +############################################################################### + +. ./version.inc.sh + +# +# Compare versions +# +if [ "$1" = "" -o "$2" = "" ] +then + echo "Missing version parameters" >&2 + exit 2 +fi + +if version_less_than $1 $2 +then + echo "$1 < $2" +else + echo "$1 >= $2" +fi diff --git a/tests/version.inc.sh b/tests/version.inc.sh new file mode 100644 index 0000000000..3630c5a1e9 --- /dev/null +++ b/tests/version.inc.sh @@ -0,0 +1,199 @@ +# Version comparison shell functions +# +############################################################################### +# +# Copyright (C) 2005, 2013 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# +############################################################################### + +############################################################################### +# +# compare version numbers to see if the first is less (older) than the second +# +############################################################################### +function version_less_than () +{ + a=$1 + b=$2 + + if [ "$a" = "$b" ] + then + return 1 + fi + + # grab the leaders + a_version=${a%%-*} a_release=${a#*-} + b_version=${b%%-*} b_release=${b#*-} + + if [ "$a_version" = "$b_version" ] + then + case "$a_release" in + rc[0-9]*) + case "$b_release" in + rc[0-9]*) + __version_less_than_dot "${a_release#rc}" "${b_release#rc}" + return $? + ;; + *) + return 0; + ;; + esac + ;; + esac + + case "$b_release" in + rc[0-9]*) + return 1; + ;; + esac + + if [ "$a_version" = "$a" -o "$b_version" = "$b" ] + then + if [ "$a_version" = "$b_version" ] + then + [ "$a_version" = "$a" ] + else + __version_less_than_dot "$a_version" "$b_version" + fi + fi + __version_less_than_dot "$a_release" "$b_release" + else + __version_less_than_dot "$a_version" "$b_version" + fi +} + +function __version_less_than_dot () +{ + a=$1 + b=$2 + + if [ "$a" = "$b" ] + then + return 1 + fi + + # grab the leaders + x=${a%%.*} + y=${b%%.*} + + if [ "$x" = "$a" -o "$y" = "$b" ] + then + if [ "$x" = "$y" ] + then + [ "$x" = "$a" ] + else + expr "$x" \< "$y" >/dev/null + fi + elif [ "$x" = "$y" ] + then + __version_less_than_dot "${a#*.}" "${b#*.}" + else + expr "$x" \< "$y" >/dev/null + fi +} + +############################################################################### +# +# Return true if the keyutils package being tested is older than the given +# version. +# +############################################################################### +function keyutils_older_than () +{ + version_less_than $KEYUTILSVER $1 +} + +############################################################################### +# +# Return true if the keyutils package being tested is at or later than the +# given version. +# +############################################################################### +function keyutils_at_or_later_than () +{ + ! keyutils_older_than $1 +} + +############################################################################### +# +# Return true if the keyutils package being tested is newer than the given +# version. +# +############################################################################### +function keyutils_newer_than () +{ + version_less_than $1 $KEYUTILSVER +} + +############################################################################### +# +# Return true if the keyutils package being tested is at or older than the +# given version. +# +############################################################################### +function keyutils_at_or_older_than () +{ + ! keyutils_newer_than $1 +} + +############################################################################### +# +# Return true if the kernel being tested is older than the given version. +# +############################################################################### +function kernel_older_than () +{ + version_less_than $KERNELVER $1 +} + +############################################################################### +# +# Return true if the kernel being tested is at or later than the given version. +# +############################################################################### +function kernel_at_or_later_than () +{ + ! kernel_older_than $1 +} + +############################################################################### +# +# Return true if the kernel being tested is a RHEL-6 kernel and is at or later +# than the given version. +# +############################################################################### +function rhel6_kernel_at_or_later_than () +{ + case $OSDIST-$OSRELEASE in + RHEL-6.*) + ! kernel_older_than $1 + ;; + *) + false + ;; + esac +} + +############################################################################### +# +# Return true if the kernel being tested is a RHEL-7 kernel and is at or later +# than the given version. +# +############################################################################### +function rhel7_kernel_at_or_later_than () +{ + case $OSDIST-$OSRELEASE in + RHEL-7.*) + ! kernel_older_than $1 + ;; + *) + false + ;; + esac +} diff --git a/version.lds b/version.lds new file mode 100644 index 0000000000..d2e4d26acc --- /dev/null +++ b/version.lds @@ -0,0 +1,100 @@ +KEYUTILS_0.3 { + + /* primary syscalls; may be overridden by glibc */ + add_key; + request_key; + keyctl; + + /* management functions */ + keyctl_chown; + keyctl_clear; + keyctl_describe; + keyctl_describe_alloc; + keyctl_get_keyring_ID; + keyctl_instantiate; + keyctl_join_session_keyring; + keyctl_link; + keyctl_negate; + keyctl_read; + keyctl_read_alloc; + keyctl_revoke; + keyctl_search; + keyctl_setperm; + keyctl_set_reqkey_keyring; + keyctl_unlink; + keyctl_update; + +}; + +KEYUTILS_1.0 { + /* management functions */ + keyctl_assume_authority; + keyctl_set_timeout; + +} KEYUTILS_0.3; + +KEYUTILS_1.3 { + /* management functions */ + keyctl_get_security; + keyctl_get_security_alloc; + keyctl_session_to_parent; + +} KEYUTILS_1.0; + +KEYUTILS_1.4 { + /* management functions */ + keyctl_reject; + keyctl_instantiate_iov; + keyctl_invalidate; + + /* utility functions */ + recursive_key_scan; + recursive_session_key_scan; + +} KEYUTILS_1.3; + +KEYUTILS_1.5 { + /* management functions */ + keyctl_get_persistent; + + /* utility functions */ + find_key_by_type_and_desc; + +} KEYUTILS_1.4; + +KEYUTILS_1.6 { + /* management functions */ + keyctl_dh_compute; + keyctl_dh_compute_alloc; + keyctl_pkey_query; + keyctl_pkey_encrypt; + keyctl_pkey_decrypt; + keyctl_pkey_sign; + keyctl_pkey_verify; + +} KEYUTILS_1.5; + +KEYUTILS_1.7 { + /* management functions */ + keyctl_restrict; + keyctl_dh_compute_kdf; + keyctl_dh_compute_kdf_alloc; + +} KEYUTILS_1.6; + +KEYUTILS_1.8 { + /* Public key cryptography functions */ + keyctl_pkey_query; + keyctl_pkey_encrypt; + keyctl_pkey_decrypt; + keyctl_pkey_sign; + keyctl_pkey_verify; + +} KEYUTILS_1.7; + +KEYUTILS_1.9 { + /* Management functions */ + keyctl_move; + keyctl_capabilities; + +} KEYUTILS_1.8; -- cgit v1.2.3-70-g09d2