├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── TODO ├── autogen.sh ├── config ├── depcomp ├── install-sh ├── missing └── mkinstalldirs ├── configure.in ├── lib └── ep_session.h └── src ├── Makefile.am ├── debug.h ├── dump.c ├── dump.h ├── elfgpg.h ├── elfhelp.h ├── elfstrings.c ├── elfstrings.h ├── main.c ├── options.h ├── sign.c ├── sign.h ├── verify.c └── verify.h /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | .*.swp 4 | autom4te.cache 5 | Makefile 6 | Makefile.in 7 | aclocal.m4 8 | config.h 9 | config.h.in 10 | config.log 11 | config.status 12 | configure 13 | src/.deps/ 14 | src/Makefile 15 | src/Makefile.in 16 | src/elfgpg 17 | stamp-h1 18 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | This file contains the name of all copyright holders. 2 | 3 | Names are sorted in order of first contribution of each author. 4 | 5 | Bart Trojanowski 6 | 7 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | elfpgp (0.1.6) unstable; urgency=low 2 | 3 | * debian/rules: handling of DEB_BUILD_OPTIONS=nostrip fixed. 4 | * Makefile.am: removed stale autoconf files from source dist. 5 | * postinst.woody, prerm.woody: removed. 6 | * ChangeLog: removed, it duplicated this file. 7 | 8 | -- Bart Trojanowski Sun, 19 Oct 2003 12:27:11 -0400 9 | 10 | elfpgp (0.1.5-2) unstable; urgency=low 11 | 12 | * fixing lintian warnings. 13 | * upgraded to automake 1.7. 14 | 15 | -- Bart Trojanowski Tue, 14 Oct 2003 22:01:17 -0400 16 | 17 | elfpgp (0.1.5-1) unstable; urgency=low 18 | 19 | * Minor bug fixes. 20 | 21 | -- Bart Trojanowski Tue, 24 May 2003 12:00:00 -0400 22 | 23 | elfpgp (0.1.4-1) unstable; urgency=low 24 | 25 | * Minor bug fixes. 26 | 27 | -- Bart Trojanowski Tue, 16 May 2003 19:00:00 -0400 28 | 29 | elfpgp (0.1.3-1) unstable; urgency=low 30 | 31 | * Minor fixes. 32 | 33 | -- Bart Trojanowski Tue, 29 Apr 2003 22:07:49 -0400 34 | 35 | elfpgp (0.1.2-1) unstable; urgency=low 36 | 37 | * Initial Debian Release. 38 | 39 | -- Bart Trojanowski Sun, 27 Apr 2003 18:54:11 -0400 40 | 41 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Basic Installation 2 | ================== 3 | 4 | These are generic installation instructions. 5 | 6 | The `configure' shell script attempts to guess correct values for 7 | various system-dependent variables used during compilation. It uses 8 | those values to create a `Makefile' in each directory of the package. 9 | It may also create one or more `.h' files containing system-dependent 10 | definitions. Finally, it creates a shell script `config.status' that 11 | you can run in the future to recreate the current configuration, a file 12 | `config.cache' that saves the results of its tests to speed up 13 | reconfiguring, and a file `config.log' containing compiler output 14 | (useful mainly for debugging `configure'). 15 | 16 | If you need to do unusual things to compile the package, please try 17 | to figure out how `configure' could check whether to do them, and mail 18 | diffs or instructions to the address given in the `README' so they can 19 | be considered for the next release. If at some point `config.cache' 20 | contains results you don't want to keep, you may remove or edit it. 21 | 22 | The file `configure.in' is used to create `configure' by a program 23 | called `autoconf'. You only need `configure.in' if you want to change 24 | it or regenerate `configure' using a newer version of `autoconf'. 25 | 26 | The simplest way to compile this package is: 27 | 28 | 1. `cd' to the directory containing the package's source code and type 29 | `./configure' to configure the package for your system. If you're 30 | using `csh' on an old version of System V, you might need to type 31 | `sh ./configure' instead to prevent `csh' from trying to execute 32 | `configure' itself. 33 | 34 | Running `configure' takes awhile. While running, it prints some 35 | messages telling which features it is checking for. 36 | 37 | 2. Type `make' to compile the package. 38 | 39 | 3. Optionally, type `make check' to run any self-tests that come with 40 | the package. 41 | 42 | 4. Type `make install' to install the programs and any data files and 43 | documentation. 44 | 45 | 5. You can remove the program binaries and object files from the 46 | source code directory by typing `make clean'. To also remove the 47 | files that `configure' created (so you can compile the package for 48 | a different kind of computer), type `make distclean'. There is 49 | also a `make maintainer-clean' target, but that is intended mainly 50 | for the package's developers. If you use it, you may have to get 51 | all sorts of other programs in order to regenerate files that came 52 | with the distribution. 53 | 54 | Compilers and Options 55 | ===================== 56 | 57 | Some systems require unusual options for compilation or linking that 58 | the `configure' script does not know about. You can give `configure' 59 | initial values for variables by setting them in the environment. Using 60 | a Bourne-compatible shell, you can do that on the command line like 61 | this: 62 | CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure 63 | 64 | Or on systems that have the `env' program, you can do it like this: 65 | env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure 66 | 67 | Compiling For Multiple Architectures 68 | ==================================== 69 | 70 | You can compile the package for more than one kind of computer at the 71 | same time, by placing the object files for each architecture in their 72 | own directory. To do this, you must use a version of `make' that 73 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 74 | directory where you want the object files and executables to go and run 75 | the `configure' script. `configure' automatically checks for the 76 | source code in the directory that `configure' is in and in `..'. 77 | 78 | If you have to use a `make' that does not supports the `VPATH' 79 | variable, you have to compile the package for one architecture at a time 80 | in the source code directory. After you have installed the package for 81 | one architecture, use `make distclean' before reconfiguring for another 82 | architecture. 83 | 84 | Installation Names 85 | ================== 86 | 87 | By default, `make install' will install the package's files in 88 | `/usr/local/bin', `/usr/local/man', etc. You can specify an 89 | installation prefix other than `/usr/local' by giving `configure' the 90 | option `--prefix=PATH'. 91 | 92 | You can specify separate installation prefixes for 93 | architecture-specific files and architecture-independent files. If you 94 | give `configure' the option `--exec-prefix=PATH', the package will use 95 | PATH as the prefix for installing programs and libraries. 96 | Documentation and other data files will still use the regular prefix. 97 | 98 | In addition, if you use an unusual directory layout you can give 99 | options like `--bindir=PATH' to specify different values for particular 100 | kinds of files. Run `configure --help' for a list of the directories 101 | you can set and what kinds of files go in them. 102 | 103 | If the package supports it, you can cause programs to be installed 104 | with an extra prefix or suffix on their names by giving `configure' the 105 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 106 | 107 | Optional Features 108 | ================= 109 | 110 | Some packages pay attention to `--enable-FEATURE' options to 111 | `configure', where FEATURE indicates an optional part of the package. 112 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 113 | is something like `gnu-as' or `x' (for the X Window System). The 114 | `README' should mention any `--enable-' and `--with-' options that the 115 | package recognizes. 116 | 117 | For packages that use the X Window System, `configure' can usually 118 | find the X include and library files automatically, but if it doesn't, 119 | you can use the `configure' options `--x-includes=DIR' and 120 | `--x-libraries=DIR' to specify their locations. 121 | 122 | Specifying the System Type 123 | ========================== 124 | 125 | There may be some features `configure' can not figure out 126 | automatically, but needs to determine by the type of host the package 127 | will run on. Usually `configure' can figure that out, but if it prints 128 | a message saying it can not guess the host type, give it the 129 | `--host=TYPE' option. TYPE can either be a short name for the system 130 | type, such as `sun4', or a canonical name with three fields: 131 | CPU-COMPANY-SYSTEM 132 | 133 | See the file `config.sub' for the possible values of each field. If 134 | `config.sub' isn't included in this package, then this package doesn't 135 | need to know the host type. 136 | 137 | If you are building compiler tools for cross-compiling, you can also 138 | use the `--target=TYPE' option to select the type of system they will 139 | produce code for and the `--build=TYPE' option to select the type of 140 | system on which you are compiling the package. 141 | 142 | Sharing Defaults 143 | ================ 144 | 145 | If you want to set default values for `configure' scripts to share, 146 | you can create a site shell script called `config.site' that gives 147 | default values for variables like `CC', `cache_file', and `prefix'. 148 | `configure' looks for `PREFIX/share/config.site' if it exists, then 149 | `PREFIX/etc/config.site' if it exists. Or, you can set the 150 | `CONFIG_SITE' environment variable to the location of the site script. 151 | A warning: not all `configure' scripts look for a site script. 152 | 153 | Operation Controls 154 | ================== 155 | 156 | `configure' recognizes the following options to control how it 157 | operates. 158 | 159 | `--cache-file=FILE' 160 | Use and save the results of the tests in FILE instead of 161 | `./config.cache'. Set FILE to `/dev/null' to disable caching, for 162 | debugging `configure'. 163 | 164 | `--help' 165 | Print a summary of the options to `configure', and exit. 166 | 167 | `--quiet' 168 | `--silent' 169 | `-q' 170 | Do not print messages saying which checks are being made. To 171 | suppress all normal output, redirect it to `/dev/null' (any error 172 | messages will still be shown). 173 | 174 | `--srcdir=DIR' 175 | Look for the package's source code in directory DIR. Usually 176 | `configure' can determine that directory automatically. 177 | 178 | `--version' 179 | Print the version of Autoconf used to generate the `configure' 180 | script, and exit. 181 | 182 | `configure' also accepts some other, not widely useful, options. 183 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2003 Bart Trojanowski 2 | # 3 | # This file is a part of the elfsign utility 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 20 | 21 | AUX_DIST = $(ac_aux_dir)/install-sh \ 22 | $(ac_aux_dir)/missing \ 23 | $(ac_aux_dir)/mkinstalldirs 24 | 25 | AUX_DIST_EXTRA = 26 | 27 | 28 | EXTRA_DIST = autogen.sh 29 | 30 | #AUTOMAKE_OPTIONS = foreign 31 | SUBDIRS = src 32 | MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config-h.in \ 33 | stamp-h.in $(AUX_DIST) 34 | 35 | ACLOCAL = aclocal -I $(ac_aux_dir) 36 | 37 | 38 | dist-hook: 39 | (cd $(distdir) && mkdir -p $(ac_aux_dir)) 40 | for file in $(AUX_DIST) $(AUX_DIST_EXTRA); do \ 41 | cp $$file $(distdir)/$$file; \ 42 | done 43 | 44 | # don't propagate autoconf generated files to source distribution. 45 | distclean-local: 46 | -rm -f config.guess config.sub config.log config.h 47 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Review the BUGS file for known issues. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | elfgpg 2 | ====== 3 | 4 | 1. About 5 | 6 | A simple (Linux) utility to inject/verify PGP signatures in elf files 7 | using GPG. 8 | 9 | This is an alpha release... please see website for details. 10 | 11 | http://www.jukie.net/~bart/elfgpg 12 | http://github.com/bartman/elfgpg 13 | 14 | 2. License & Warranty 15 | 16 | This software is offered to you with no warranty. It is released under 17 | the terms and conditions of the GPL; see the COPYING files for details. 18 | 19 | 20 | 3. Dependencies 21 | 22 | You will need to install libelf development package (or source + headers). 23 | On Debian you can run: 24 | 25 | apt-get install libelfg0-dev libgpgme-dev 26 | 27 | Currently this package has only been tested on Linux. I don't expect it to 28 | be extremely portable at this time. 29 | 30 | More to the point, I've built and tested it with the following Debian 31 | and Redhat configurations: 32 | 33 | Debian/testing RedHat/7.2 34 | kernel 2.4.20 2.4.20 35 | gcc 2.95.4-17 2.96 36 | libc6-dev 2.3.1-16 2.2.5-32 37 | libgpgme-dev 0.3.15-1 0.3.5-fr1 38 | libelfg0-dev 0.8.2-1 0.7.0-1 39 | 40 | 41 | 4. Bugs & Issues 42 | 43 | The is a list of known issues in the BUGS file. If there are any other 44 | issues you have found, I would appreciate if you send me some details. 45 | 46 | 47 | 48 | Bart Trojanowski 49 | 50 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - prepare_elfgpg_sections need cleanup of something fails. 2 | - elfgpg --remove is needed 3 | - write a man page 4 | - write up the file format (extra elf sections) 5 | - should sign the .pgptab section as well 6 | - should make sure on --verify that all 'important' sections are actually signed 7 | - remove duplication from sign.c, verify.c and dump.c 8 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | aclocal -I config 3 | autoheader 4 | automake --add-missing --copy 5 | autoconf 6 | -------------------------------------------------------------------------------- /config/depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # depcomp - compile a program generating dependencies as side-effects 4 | # Copyright 1999, 2000 Free Software Foundation, Inc. 5 | 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 | # 02111-1307, USA. 20 | 21 | # As a special exception to the GNU General Public License, if you 22 | # distribute this file as part of a program that contains a 23 | # configuration script generated by Autoconf, you may include it under 24 | # the same distribution terms that you use for the rest of that program. 25 | 26 | # Originally written by Alexandre Oliva . 27 | 28 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 29 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 30 | exit 1 31 | fi 32 | # `libtool' can also be set to `yes' or `no'. 33 | 34 | if test -z "$depfile"; then 35 | base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` 36 | dir=`echo "$object" | sed 's,/.*$,/,'` 37 | if test "$dir" = "$object"; then 38 | dir= 39 | fi 40 | # FIXME: should be _deps on DOS. 41 | depfile="$dir.deps/$base" 42 | fi 43 | 44 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 45 | 46 | rm -f "$tmpdepfile" 47 | 48 | # Some modes work just like other modes, but use different flags. We 49 | # parameterize here, but still list the modes in the big case below, 50 | # to make depend.m4 easier to write. Note that we *cannot* use a case 51 | # here, because this file can only contain one case statement. 52 | if test "$depmode" = hp; then 53 | # HP compiler uses -M and no extra arg. 54 | gccflag=-M 55 | depmode=gcc 56 | fi 57 | 58 | if test "$depmode" = dashXmstdout; then 59 | # This is just like dashmstdout with a different argument. 60 | dashmflag=-xM 61 | depmode=dashmstdout 62 | fi 63 | 64 | case "$depmode" in 65 | gcc3) 66 | ## gcc 3 implements dependency tracking that does exactly what 67 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 68 | ## it if -MD -MP comes after the -MF stuff. Hmm. 69 | "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" 70 | stat=$? 71 | if test $stat -eq 0; then : 72 | else 73 | rm -f "$tmpdepfile" 74 | exit $stat 75 | fi 76 | mv "$tmpdepfile" "$depfile" 77 | ;; 78 | 79 | gcc) 80 | ## There are various ways to get dependency output from gcc. Here's 81 | ## why we pick this rather obscure method: 82 | ## - Don't want to use -MD because we'd like the dependencies to end 83 | ## up in a subdir. Having to rename by hand is ugly. 84 | ## (We might end up doing this anyway to support other compilers.) 85 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 86 | ## -MM, not -M (despite what the docs say). 87 | ## - Using -M directly means running the compiler twice (even worse 88 | ## than renaming). 89 | if test -z "$gccflag"; then 90 | gccflag=-MD, 91 | fi 92 | "$@" -Wp,"$gccflag$tmpdepfile" 93 | stat=$? 94 | if test $stat -eq 0; then : 95 | else 96 | rm -f "$tmpdepfile" 97 | exit $stat 98 | fi 99 | rm -f "$depfile" 100 | echo "$object : \\" > "$depfile" 101 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 102 | ## The second -e expression handles DOS-style file names with drive letters. 103 | sed -e 's/^[^:]*: / /' \ 104 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 105 | ## This next piece of magic avoids the `deleted header file' problem. 106 | ## The problem is that when a header file which appears in a .P file 107 | ## is deleted, the dependency causes make to die (because there is 108 | ## typically no way to rebuild the header). We avoid this by adding 109 | ## dummy dependencies for each header file. Too bad gcc doesn't do 110 | ## this for us directly. 111 | tr ' ' ' 112 | ' < "$tmpdepfile" | 113 | ## Some versions of gcc put a space before the `:'. On the theory 114 | ## that the space means something, we add a space to the output as 115 | ## well. 116 | ## Some versions of the HPUX 10.20 sed can't process this invocation 117 | ## correctly. Breaking it into two sed invocations is a workaround. 118 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 119 | rm -f "$tmpdepfile" 120 | ;; 121 | 122 | hp) 123 | # This case exists only to let depend.m4 do its work. It works by 124 | # looking at the text of this script. This case will never be run, 125 | # since it is checked for above. 126 | exit 1 127 | ;; 128 | 129 | sgi) 130 | if test "$libtool" = yes; then 131 | "$@" "-Wp,-MDupdate,$tmpdepfile" 132 | else 133 | "$@" -MDupdate "$tmpdepfile" 134 | fi 135 | stat=$? 136 | if test $stat -eq 0; then : 137 | else 138 | rm -f "$tmpdepfile" 139 | exit $stat 140 | fi 141 | rm -f "$depfile" 142 | 143 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 144 | echo "$object : \\" > "$depfile" 145 | 146 | # Clip off the initial element (the dependent). Don't try to be 147 | # clever and replace this with sed code, as IRIX sed won't handle 148 | # lines with more than a fixed number of characters (4096 in 149 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 150 | # the IRIX cc adds comments like `#:fec' to the end of the 151 | # dependency line. 152 | tr ' ' ' 153 | ' < "$tmpdepfile" \ 154 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 155 | tr ' 156 | ' ' ' >> $depfile 157 | echo >> $depfile 158 | 159 | # The second pass generates a dummy entry for each header file. 160 | tr ' ' ' 161 | ' < "$tmpdepfile" \ 162 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 163 | >> $depfile 164 | else 165 | # The sourcefile does not contain any dependencies, so just 166 | # store a dummy comment line, to avoid errors with the Makefile 167 | # "include basename.Plo" scheme. 168 | echo "#dummy" > "$depfile" 169 | fi 170 | rm -f "$tmpdepfile" 171 | ;; 172 | 173 | aix) 174 | # The C for AIX Compiler uses -M and outputs the dependencies 175 | # in a .u file. This file always lives in the current directory. 176 | # Also, the AIX compiler puts `$object:' at the start of each line; 177 | # $object doesn't have directory information. 178 | stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` 179 | tmpdepfile="$stripped.u" 180 | outname="$stripped.o" 181 | if test "$libtool" = yes; then 182 | "$@" -Wc,-M 183 | else 184 | "$@" -M 185 | fi 186 | 187 | stat=$? 188 | if test $stat -eq 0; then : 189 | else 190 | rm -f "$tmpdepfile" 191 | exit $stat 192 | fi 193 | 194 | if test -f "$tmpdepfile"; then 195 | # Each line is of the form `foo.o: dependent.h'. 196 | # Do two passes, one to just change these to 197 | # `$object: dependent.h' and one to simply `dependent.h:'. 198 | sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" 199 | sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" 200 | else 201 | # The sourcefile does not contain any dependencies, so just 202 | # store a dummy comment line, to avoid errors with the Makefile 203 | # "include basename.Plo" scheme. 204 | echo "#dummy" > "$depfile" 205 | fi 206 | rm -f "$tmpdepfile" 207 | ;; 208 | 209 | icc) 210 | # Intel's C compiler understands `-MD -MF file'. However on 211 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 212 | # ICC 7.0 will fill foo.d with something like 213 | # foo.o: sub/foo.c 214 | # foo.o: sub/foo.h 215 | # which is wrong. We want: 216 | # sub/foo.o: sub/foo.c 217 | # sub/foo.o: sub/foo.h 218 | # sub/foo.c: 219 | # sub/foo.h: 220 | # ICC 7.1 will output 221 | # foo.o: sub/foo.c sub/foo.h 222 | # and will wrap long lines using \ : 223 | # foo.o: sub/foo.c ... \ 224 | # sub/foo.h ... \ 225 | # ... 226 | 227 | "$@" -MD -MF "$tmpdepfile" 228 | stat=$? 229 | if test $stat -eq 0; then : 230 | else 231 | rm -f "$tmpdepfile" 232 | exit $stat 233 | fi 234 | rm -f "$depfile" 235 | # Each line is of the form `foo.o: dependent.h', 236 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 237 | # Do two passes, one to just change these to 238 | # `$object: dependent.h' and one to simply `dependent.h:'. 239 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 240 | # Some versions of the HPUX 10.20 sed can't process this invocation 241 | # correctly. Breaking it into two sed invocations is a workaround. 242 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 243 | sed -e 's/$/ :/' >> "$depfile" 244 | rm -f "$tmpdepfile" 245 | ;; 246 | 247 | tru64) 248 | # The Tru64 compiler uses -MD to generate dependencies as a side 249 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 250 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 251 | # dependencies in `foo.d' instead, so we check for that too. 252 | # Subdirectories are respected. 253 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 254 | test "x$dir" = "x$object" && dir= 255 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 256 | 257 | if test "$libtool" = yes; then 258 | tmpdepfile1="$dir.libs/$base.lo.d" 259 | tmpdepfile2="$dir.libs/$base.d" 260 | "$@" -Wc,-MD 261 | else 262 | tmpdepfile1="$dir$base.o.d" 263 | tmpdepfile2="$dir$base.d" 264 | "$@" -MD 265 | fi 266 | 267 | stat=$? 268 | if test $stat -eq 0; then : 269 | else 270 | rm -f "$tmpdepfile1" "$tmpdepfile2" 271 | exit $stat 272 | fi 273 | 274 | if test -f "$tmpdepfile1"; then 275 | tmpdepfile="$tmpdepfile1" 276 | else 277 | tmpdepfile="$tmpdepfile2" 278 | fi 279 | if test -f "$tmpdepfile"; then 280 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 281 | # That's a space and a tab in the []. 282 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 283 | else 284 | echo "#dummy" > "$depfile" 285 | fi 286 | rm -f "$tmpdepfile" 287 | ;; 288 | 289 | #nosideeffect) 290 | # This comment above is used by automake to tell side-effect 291 | # dependency tracking mechanisms from slower ones. 292 | 293 | dashmstdout) 294 | # Important note: in order to support this mode, a compiler *must* 295 | # always write the proprocessed file to stdout, regardless of -o. 296 | "$@" || exit $? 297 | 298 | # Remove the call to Libtool. 299 | if test "$libtool" = yes; then 300 | while test $1 != '--mode=compile'; do 301 | shift 302 | done 303 | shift 304 | fi 305 | 306 | # Remove `-o $object'. 307 | IFS=" " 308 | for arg 309 | do 310 | case $arg in 311 | -o) 312 | shift 313 | ;; 314 | $object) 315 | shift 316 | ;; 317 | *) 318 | set fnord "$@" "$arg" 319 | shift # fnord 320 | shift # $arg 321 | ;; 322 | esac 323 | done 324 | 325 | test -z "$dashmflag" && dashmflag=-M 326 | # Require at least two characters before searching for `:' 327 | # in the target name. This is to cope with DOS-style filenames: 328 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 329 | "$@" $dashmflag | 330 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 331 | rm -f "$depfile" 332 | cat < "$tmpdepfile" > "$depfile" 333 | tr ' ' ' 334 | ' < "$tmpdepfile" | \ 335 | ## Some versions of the HPUX 10.20 sed can't process this invocation 336 | ## correctly. Breaking it into two sed invocations is a workaround. 337 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 338 | rm -f "$tmpdepfile" 339 | ;; 340 | 341 | dashXmstdout) 342 | # This case only exists to satisfy depend.m4. It is never actually 343 | # run, as this mode is specially recognized in the preamble. 344 | exit 1 345 | ;; 346 | 347 | makedepend) 348 | "$@" || exit $? 349 | # Remove any Libtool call 350 | if test "$libtool" = yes; then 351 | while test $1 != '--mode=compile'; do 352 | shift 353 | done 354 | shift 355 | fi 356 | # X makedepend 357 | shift 358 | cleared=no 359 | for arg in "$@"; do 360 | case $cleared in 361 | no) 362 | set ""; shift 363 | cleared=yes ;; 364 | esac 365 | case "$arg" in 366 | -D*|-I*) 367 | set fnord "$@" "$arg"; shift ;; 368 | # Strip any option that makedepend may not understand. Remove 369 | # the object too, otherwise makedepend will parse it as a source file. 370 | -*|$object) 371 | ;; 372 | *) 373 | set fnord "$@" "$arg"; shift ;; 374 | esac 375 | done 376 | obj_suffix="`echo $object | sed 's/^.*\././'`" 377 | touch "$tmpdepfile" 378 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 379 | rm -f "$depfile" 380 | cat < "$tmpdepfile" > "$depfile" 381 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 382 | ' | \ 383 | ## Some versions of the HPUX 10.20 sed can't process this invocation 384 | ## correctly. Breaking it into two sed invocations is a workaround. 385 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 386 | rm -f "$tmpdepfile" "$tmpdepfile".bak 387 | ;; 388 | 389 | cpp) 390 | # Important note: in order to support this mode, a compiler *must* 391 | # always write the proprocessed file to stdout. 392 | "$@" || exit $? 393 | 394 | # Remove the call to Libtool. 395 | if test "$libtool" = yes; then 396 | while test $1 != '--mode=compile'; do 397 | shift 398 | done 399 | shift 400 | fi 401 | 402 | # Remove `-o $object'. 403 | IFS=" " 404 | for arg 405 | do 406 | case $arg in 407 | -o) 408 | shift 409 | ;; 410 | $object) 411 | shift 412 | ;; 413 | *) 414 | set fnord "$@" "$arg" 415 | shift # fnord 416 | shift # $arg 417 | ;; 418 | esac 419 | done 420 | 421 | "$@" -E | 422 | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 423 | sed '$ s: \\$::' > "$tmpdepfile" 424 | rm -f "$depfile" 425 | echo "$object : \\" > "$depfile" 426 | cat < "$tmpdepfile" >> "$depfile" 427 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 428 | rm -f "$tmpdepfile" 429 | ;; 430 | 431 | msvisualcpp) 432 | # Important note: in order to support this mode, a compiler *must* 433 | # always write the proprocessed file to stdout, regardless of -o, 434 | # because we must use -o when running libtool. 435 | "$@" || exit $? 436 | IFS=" " 437 | for arg 438 | do 439 | case "$arg" in 440 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 441 | set fnord "$@" 442 | shift 443 | shift 444 | ;; 445 | *) 446 | set fnord "$@" "$arg" 447 | shift 448 | shift 449 | ;; 450 | esac 451 | done 452 | "$@" -E | 453 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" 454 | rm -f "$depfile" 455 | echo "$object : \\" > "$depfile" 456 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 457 | echo " " >> "$depfile" 458 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" 459 | rm -f "$tmpdepfile" 460 | ;; 461 | 462 | none) 463 | exec "$@" 464 | ;; 465 | 466 | *) 467 | echo "Unknown depmode $depmode" 1>&2 468 | exit 1 469 | ;; 470 | esac 471 | 472 | exit 0 473 | -------------------------------------------------------------------------------- /config/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # 5 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 6 | # later released in X11R6 (xc/config/util/install.sh) with the 7 | # following copyright and license. 8 | # 9 | # Copyright (C) 1994 X Consortium 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the "Software"), to 13 | # deal in the Software without restriction, including without limitation the 14 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | # sell copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included in 19 | # all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 26 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | # 28 | # Except as contained in this notice, the name of the X Consortium shall not 29 | # be used in advertising or otherwise to promote the sale, use or other deal- 30 | # ings in this Software without prior written authorization from the X Consor- 31 | # tium. 32 | # 33 | # 34 | # FSF changes to this file are in the public domain. 35 | # 36 | # Calling this script install-sh is preferred over install.sh, to prevent 37 | # `make' implicit rules from creating a file called install from it 38 | # when there is no Makefile. 39 | # 40 | # This script is compatible with the BSD install script, but was written 41 | # from scratch. It can only install one file at a time, a restriction 42 | # shared with many OS's install programs. 43 | 44 | 45 | # set DOITPROG to echo to test this script 46 | 47 | # Don't use :- since 4.3BSD and earlier shells don't like it. 48 | doit="${DOITPROG-}" 49 | 50 | 51 | # put in absolute paths if you don't have them in your path; or use env. vars. 52 | 53 | mvprog="${MVPROG-mv}" 54 | cpprog="${CPPROG-cp}" 55 | chmodprog="${CHMODPROG-chmod}" 56 | chownprog="${CHOWNPROG-chown}" 57 | chgrpprog="${CHGRPPROG-chgrp}" 58 | stripprog="${STRIPPROG-strip}" 59 | rmprog="${RMPROG-rm}" 60 | mkdirprog="${MKDIRPROG-mkdir}" 61 | 62 | transformbasename="" 63 | transform_arg="" 64 | instcmd="$mvprog" 65 | chmodcmd="$chmodprog 0755" 66 | chowncmd="" 67 | chgrpcmd="" 68 | stripcmd="" 69 | rmcmd="$rmprog -f" 70 | mvcmd="$mvprog" 71 | src="" 72 | dst="" 73 | dir_arg="" 74 | 75 | while [ x"$1" != x ]; do 76 | case $1 in 77 | -c) instcmd=$cpprog 78 | shift 79 | continue;; 80 | 81 | -d) dir_arg=true 82 | shift 83 | continue;; 84 | 85 | -m) chmodcmd="$chmodprog $2" 86 | shift 87 | shift 88 | continue;; 89 | 90 | -o) chowncmd="$chownprog $2" 91 | shift 92 | shift 93 | continue;; 94 | 95 | -g) chgrpcmd="$chgrpprog $2" 96 | shift 97 | shift 98 | continue;; 99 | 100 | -s) stripcmd=$stripprog 101 | shift 102 | continue;; 103 | 104 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 105 | shift 106 | continue;; 107 | 108 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 109 | shift 110 | continue;; 111 | 112 | *) if [ x"$src" = x ] 113 | then 114 | src=$1 115 | else 116 | # this colon is to work around a 386BSD /bin/sh bug 117 | : 118 | dst=$1 119 | fi 120 | shift 121 | continue;; 122 | esac 123 | done 124 | 125 | if [ x"$src" = x ] 126 | then 127 | echo "$0: no input file specified" >&2 128 | exit 1 129 | else 130 | : 131 | fi 132 | 133 | if [ x"$dir_arg" != x ]; then 134 | dst=$src 135 | src="" 136 | 137 | if [ -d "$dst" ]; then 138 | instcmd=: 139 | chmodcmd="" 140 | else 141 | instcmd=$mkdirprog 142 | fi 143 | else 144 | 145 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 146 | # might cause directories to be created, which would be especially bad 147 | # if $src (and thus $dsttmp) contains '*'. 148 | 149 | if [ -f "$src" ] || [ -d "$src" ] 150 | then 151 | : 152 | else 153 | echo "$0: $src does not exist" >&2 154 | exit 1 155 | fi 156 | 157 | if [ x"$dst" = x ] 158 | then 159 | echo "$0: no destination specified" >&2 160 | exit 1 161 | else 162 | : 163 | fi 164 | 165 | # If destination is a directory, append the input filename; if your system 166 | # does not like double slashes in filenames, you may need to add some logic 167 | 168 | if [ -d "$dst" ] 169 | then 170 | dst=$dst/`basename "$src"` 171 | else 172 | : 173 | fi 174 | fi 175 | 176 | ## this sed command emulates the dirname command 177 | dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 178 | 179 | # Make sure that the destination directory exists. 180 | # this part is taken from Noah Friedman's mkinstalldirs script 181 | 182 | # Skip lots of stat calls in the usual case. 183 | if [ ! -d "$dstdir" ]; then 184 | defaultIFS=' 185 | ' 186 | IFS="${IFS-$defaultIFS}" 187 | 188 | oIFS=$IFS 189 | # Some sh's can't handle IFS=/ for some reason. 190 | IFS='%' 191 | set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 192 | IFS=$oIFS 193 | 194 | pathcomp='' 195 | 196 | while [ $# -ne 0 ] ; do 197 | pathcomp=$pathcomp$1 198 | shift 199 | 200 | if [ ! -d "$pathcomp" ] ; 201 | then 202 | $mkdirprog "$pathcomp" 203 | else 204 | : 205 | fi 206 | 207 | pathcomp=$pathcomp/ 208 | done 209 | fi 210 | 211 | if [ x"$dir_arg" != x ] 212 | then 213 | $doit $instcmd "$dst" && 214 | 215 | if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && 216 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && 217 | if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && 218 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi 219 | else 220 | 221 | # If we're going to rename the final executable, determine the name now. 222 | 223 | if [ x"$transformarg" = x ] 224 | then 225 | dstfile=`basename "$dst"` 226 | else 227 | dstfile=`basename "$dst" $transformbasename | 228 | sed $transformarg`$transformbasename 229 | fi 230 | 231 | # don't allow the sed command to completely eliminate the filename 232 | 233 | if [ x"$dstfile" = x ] 234 | then 235 | dstfile=`basename "$dst"` 236 | else 237 | : 238 | fi 239 | 240 | # Make a couple of temp file names in the proper directory. 241 | 242 | dsttmp=$dstdir/_inst.$$_ 243 | rmtmp=$dstdir/_rm.$$_ 244 | 245 | # Trap to clean up temp files at exit. 246 | 247 | trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 248 | trap '(exit $?); exit' 1 2 13 15 249 | 250 | # Move or copy the file name to the temp name 251 | 252 | $doit $instcmd "$src" "$dsttmp" && 253 | 254 | # and set any options; do chmod last to preserve setuid bits 255 | 256 | # If any of these fail, we abort the whole thing. If we want to 257 | # ignore errors from any of these, just make sure not to ignore 258 | # errors from the above "$doit $instcmd $src $dsttmp" command. 259 | 260 | if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && 261 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && 262 | if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && 263 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && 264 | 265 | # Now remove or move aside any old file at destination location. We try this 266 | # two ways since rm can't unlink itself on some systems and the destination 267 | # file might be busy for other reasons. In this case, the final cleanup 268 | # might fail but the new file should still install successfully. 269 | 270 | { 271 | if [ -f "$dstdir/$dstfile" ] 272 | then 273 | $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || 274 | $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || 275 | { 276 | echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 277 | (exit 1); exit 278 | } 279 | else 280 | : 281 | fi 282 | } && 283 | 284 | # Now rename the file to the real destination. 285 | 286 | $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 287 | 288 | fi && 289 | 290 | # The final little trick to "correctly" pass the exit status to the exit trap. 291 | 292 | { 293 | (exit 0); exit 294 | } 295 | -------------------------------------------------------------------------------- /config/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | # Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. 4 | # Originally by Fran,cois Pinard , 1996. 5 | 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 | # 02111-1307, USA. 20 | 21 | # As a special exception to the GNU General Public License, if you 22 | # distribute this file as part of a program that contains a 23 | # configuration script generated by Autoconf, you may include it under 24 | # the same distribution terms that you use for the rest of that program. 25 | 26 | if test $# -eq 0; then 27 | echo 1>&2 "Try \`$0 --help' for more information" 28 | exit 1 29 | fi 30 | 31 | run=: 32 | 33 | # In the cases where this matters, `missing' is being run in the 34 | # srcdir already. 35 | if test -f configure.ac; then 36 | configure_ac=configure.ac 37 | else 38 | configure_ac=configure.in 39 | fi 40 | 41 | case "$1" in 42 | --run) 43 | # Try to run requested program, and just exit if it succeeds. 44 | run= 45 | shift 46 | "$@" && exit 0 47 | ;; 48 | esac 49 | 50 | # If it does not exist, or fails to run (possibly an outdated version), 51 | # try to emulate it. 52 | case "$1" in 53 | 54 | -h|--h|--he|--hel|--help) 55 | echo "\ 56 | $0 [OPTION]... PROGRAM [ARGUMENT]... 57 | 58 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 59 | error status if there is no known handling for PROGRAM. 60 | 61 | Options: 62 | -h, --help display this help and exit 63 | -v, --version output version information and exit 64 | --run try to run the given command, and emulate it if it fails 65 | 66 | Supported PROGRAM values: 67 | aclocal touch file \`aclocal.m4' 68 | autoconf touch file \`configure' 69 | autoheader touch file \`config.h.in' 70 | automake touch all \`Makefile.in' files 71 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 72 | flex create \`lex.yy.c', if possible, from existing .c 73 | help2man touch the output file 74 | lex create \`lex.yy.c', if possible, from existing .c 75 | makeinfo touch the output file 76 | tar try tar, gnutar, gtar, then tar without non-portable flags 77 | yacc create \`y.tab.[ch]', if possible, from existing .[ch]" 78 | ;; 79 | 80 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 81 | echo "missing 0.4 - GNU automake" 82 | ;; 83 | 84 | -*) 85 | echo 1>&2 "$0: Unknown \`$1' option" 86 | echo 1>&2 "Try \`$0 --help' for more information" 87 | exit 1 88 | ;; 89 | 90 | aclocal*) 91 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 92 | # We have it, but it failed. 93 | exit 1 94 | fi 95 | 96 | echo 1>&2 "\ 97 | WARNING: \`$1' is missing on your system. You should only need it if 98 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 99 | to install the \`Automake' and \`Perl' packages. Grab them from 100 | any GNU archive site." 101 | touch aclocal.m4 102 | ;; 103 | 104 | autoconf) 105 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 106 | # We have it, but it failed. 107 | exit 1 108 | fi 109 | 110 | echo 1>&2 "\ 111 | WARNING: \`$1' is missing on your system. You should only need it if 112 | you modified \`${configure_ac}'. You might want to install the 113 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 114 | archive site." 115 | touch configure 116 | ;; 117 | 118 | autoheader) 119 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 120 | # We have it, but it failed. 121 | exit 1 122 | fi 123 | 124 | echo 1>&2 "\ 125 | WARNING: \`$1' is missing on your system. You should only need it if 126 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 127 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 128 | from any GNU archive site." 129 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 130 | test -z "$files" && files="config.h" 131 | touch_files= 132 | for f in $files; do 133 | case "$f" in 134 | *:*) touch_files="$touch_files "`echo "$f" | 135 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 136 | *) touch_files="$touch_files $f.in";; 137 | esac 138 | done 139 | touch $touch_files 140 | ;; 141 | 142 | automake*) 143 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 144 | # We have it, but it failed. 145 | exit 1 146 | fi 147 | 148 | echo 1>&2 "\ 149 | WARNING: \`$1' is missing on your system. You should only need it if 150 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 151 | You might want to install the \`Automake' and \`Perl' packages. 152 | Grab them from any GNU archive site." 153 | find . -type f -name Makefile.am -print | 154 | sed 's/\.am$/.in/' | 155 | while read f; do touch "$f"; done 156 | ;; 157 | 158 | autom4te) 159 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 160 | # We have it, but it failed. 161 | exit 1 162 | fi 163 | 164 | echo 1>&2 "\ 165 | WARNING: \`$1' is needed, and you do not seem to have it handy on your 166 | system. You might have modified some files without having the 167 | proper tools for further handling them. 168 | You can get \`$1Help2man' as part of \`Autoconf' from any GNU 169 | archive site." 170 | 171 | file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` 172 | test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` 173 | if test -f "$file"; then 174 | touch $file 175 | else 176 | test -z "$file" || exec >$file 177 | echo "#! /bin/sh" 178 | echo "# Created by GNU Automake missing as a replacement of" 179 | echo "# $ $@" 180 | echo "exit 0" 181 | chmod +x $file 182 | exit 1 183 | fi 184 | ;; 185 | 186 | bison|yacc) 187 | echo 1>&2 "\ 188 | WARNING: \`$1' is missing on your system. You should only need it if 189 | you modified a \`.y' file. You may need the \`Bison' package 190 | in order for those modifications to take effect. You can get 191 | \`Bison' from any GNU archive site." 192 | rm -f y.tab.c y.tab.h 193 | if [ $# -ne 1 ]; then 194 | eval LASTARG="\${$#}" 195 | case "$LASTARG" in 196 | *.y) 197 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 198 | if [ -f "$SRCFILE" ]; then 199 | cp "$SRCFILE" y.tab.c 200 | fi 201 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 202 | if [ -f "$SRCFILE" ]; then 203 | cp "$SRCFILE" y.tab.h 204 | fi 205 | ;; 206 | esac 207 | fi 208 | if [ ! -f y.tab.h ]; then 209 | echo >y.tab.h 210 | fi 211 | if [ ! -f y.tab.c ]; then 212 | echo 'main() { return 0; }' >y.tab.c 213 | fi 214 | ;; 215 | 216 | lex|flex) 217 | echo 1>&2 "\ 218 | WARNING: \`$1' is missing on your system. You should only need it if 219 | you modified a \`.l' file. You may need the \`Flex' package 220 | in order for those modifications to take effect. You can get 221 | \`Flex' from any GNU archive site." 222 | rm -f lex.yy.c 223 | if [ $# -ne 1 ]; then 224 | eval LASTARG="\${$#}" 225 | case "$LASTARG" in 226 | *.l) 227 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 228 | if [ -f "$SRCFILE" ]; then 229 | cp "$SRCFILE" lex.yy.c 230 | fi 231 | ;; 232 | esac 233 | fi 234 | if [ ! -f lex.yy.c ]; then 235 | echo 'main() { return 0; }' >lex.yy.c 236 | fi 237 | ;; 238 | 239 | help2man) 240 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 241 | # We have it, but it failed. 242 | exit 1 243 | fi 244 | 245 | echo 1>&2 "\ 246 | WARNING: \`$1' is missing on your system. You should only need it if 247 | you modified a dependency of a manual page. You may need the 248 | \`Help2man' package in order for those modifications to take 249 | effect. You can get \`Help2man' from any GNU archive site." 250 | 251 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 252 | if test -z "$file"; then 253 | file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` 254 | fi 255 | if [ -f "$file" ]; then 256 | touch $file 257 | else 258 | test -z "$file" || exec >$file 259 | echo ".ab help2man is required to generate this page" 260 | exit 1 261 | fi 262 | ;; 263 | 264 | makeinfo) 265 | if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then 266 | # We have makeinfo, but it failed. 267 | exit 1 268 | fi 269 | 270 | echo 1>&2 "\ 271 | WARNING: \`$1' is missing on your system. You should only need it if 272 | you modified a \`.texi' or \`.texinfo' file, or any other file 273 | indirectly affecting the aspect of the manual. The spurious 274 | call might also be the consequence of using a buggy \`make' (AIX, 275 | DU, IRIX). You might want to install the \`Texinfo' package or 276 | the \`GNU make' package. Grab either from any GNU archive site." 277 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 278 | if test -z "$file"; then 279 | file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 280 | file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` 281 | fi 282 | touch $file 283 | ;; 284 | 285 | tar) 286 | shift 287 | if test -n "$run"; then 288 | echo 1>&2 "ERROR: \`tar' requires --run" 289 | exit 1 290 | fi 291 | 292 | # We have already tried tar in the generic part. 293 | # Look for gnutar/gtar before invocation to avoid ugly error 294 | # messages. 295 | if (gnutar --version > /dev/null 2>&1); then 296 | gnutar "$@" && exit 0 297 | fi 298 | if (gtar --version > /dev/null 2>&1); then 299 | gtar "$@" && exit 0 300 | fi 301 | firstarg="$1" 302 | if shift; then 303 | case "$firstarg" in 304 | *o*) 305 | firstarg=`echo "$firstarg" | sed s/o//` 306 | tar "$firstarg" "$@" && exit 0 307 | ;; 308 | esac 309 | case "$firstarg" in 310 | *h*) 311 | firstarg=`echo "$firstarg" | sed s/h//` 312 | tar "$firstarg" "$@" && exit 0 313 | ;; 314 | esac 315 | fi 316 | 317 | echo 1>&2 "\ 318 | WARNING: I can't seem to be able to run \`tar' with the given arguments. 319 | You may want to install GNU tar or Free paxutils, or check the 320 | command line arguments." 321 | exit 1 322 | ;; 323 | 324 | *) 325 | echo 1>&2 "\ 326 | WARNING: \`$1' is needed, and you do not seem to have it handy on your 327 | system. You might have modified some files without having the 328 | proper tools for further handling them. Check the \`README' file, 329 | it often tells you about the needed prerequirements for installing 330 | this package. You may also peek at any GNU archive site, in case 331 | some other package would contain this missing \`$1' program." 332 | exit 1 333 | ;; 334 | esac 335 | 336 | exit 0 337 | -------------------------------------------------------------------------------- /config/mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | errstatus=0 8 | dirmode="" 9 | 10 | usage="\ 11 | Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." 12 | 13 | # process command line arguments 14 | while test $# -gt 0 ; do 15 | case $1 in 16 | -h | --help | --h*) # -h for help 17 | echo "$usage" 1>&2 18 | exit 0 19 | ;; 20 | -m) # -m PERM arg 21 | shift 22 | test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } 23 | dirmode=$1 24 | shift 25 | ;; 26 | --) # stop option processing 27 | shift 28 | break 29 | ;; 30 | -*) # unknown option 31 | echo "$usage" 1>&2 32 | exit 1 33 | ;; 34 | *) # first non-opt arg 35 | break 36 | ;; 37 | esac 38 | done 39 | 40 | for file 41 | do 42 | if test -d "$file"; then 43 | shift 44 | else 45 | break 46 | fi 47 | done 48 | 49 | case $# in 50 | 0) exit 0 ;; 51 | esac 52 | 53 | case $dirmode in 54 | '') 55 | if mkdir -p -- . 2>/dev/null; then 56 | echo "mkdir -p -- $*" 57 | exec mkdir -p -- "$@" 58 | fi 59 | ;; 60 | *) 61 | if mkdir -m "$dirmode" -p -- . 2>/dev/null; then 62 | echo "mkdir -m $dirmode -p -- $*" 63 | exec mkdir -m "$dirmode" -p -- "$@" 64 | fi 65 | ;; 66 | esac 67 | 68 | for file 69 | do 70 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 71 | shift 72 | 73 | pathcomp= 74 | for d 75 | do 76 | pathcomp="$pathcomp$d" 77 | case $pathcomp in 78 | -*) pathcomp=./$pathcomp ;; 79 | esac 80 | 81 | if test ! -d "$pathcomp"; then 82 | echo "mkdir $pathcomp" 83 | 84 | mkdir "$pathcomp" || lasterr=$? 85 | 86 | if test ! -d "$pathcomp"; then 87 | errstatus=$lasterr 88 | else 89 | if test ! -z "$dirmode"; then 90 | echo "chmod $dirmode $pathcomp" 91 | lasterr="" 92 | chmod "$dirmode" "$pathcomp" || lasterr=$? 93 | 94 | if test ! -z "$lasterr"; then 95 | errstatus=$lasterr 96 | fi 97 | fi 98 | fi 99 | fi 100 | 101 | pathcomp="$pathcomp/" 102 | done 103 | done 104 | 105 | exit $errstatus 106 | 107 | # Local Variables: 108 | # mode: shell-script 109 | # sh-indentation: 2 110 | # End: 111 | # mkinstalldirs ends here 112 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2003 Bart Trojanowski 2 | # 3 | # This file is a part of the elfsign utility 4 | # Process this file with autoconf to produce a configure script. 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 21 | 22 | AC_INIT(src/main.c) 23 | AC_CONFIG_AUX_DIR(config) 24 | AM_CONFIG_HEADER(config.h) 25 | 26 | AM_INIT_AUTOMAKE(elfgpg, 0.1.6) 27 | 28 | dnl Checks for programs. 29 | AC_PROG_CC 30 | 31 | dnl Checks for libraries. 32 | AC_CHECK_LIB(elf, elf_version,, [ 33 | echo "ERROR: You need libelf to build elfgpg."; 34 | AC_MSG_ERROR([Fatal: libelf not found.])]) 35 | AC_CHECK_LIB(gpgme, gpgme_new,, [ 36 | echo "ERROR: You need libgpgme to build elfgpg."; 37 | AC_MSG_ERROR([Fatal: libgpgme not found.])]) 38 | 39 | dnl Checks for header files. 40 | AC_HEADER_STDC 41 | AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h string.h sys/stat.h sys/types.h termios.h unistd.h getopt.h],, [ 42 | echo "ERROR: You need libc to build elfgpg."; 43 | AC_MSG_ERROR([Fatal: libc headers not found.])]) 44 | AC_CHECK_HEADERS(libelf.h,, [ 45 | echo "ERROR: You need libelf to build elfgpg."; 46 | AC_MSG_ERROR([Fatal: elf headers not found.])]) 47 | AC_CHECK_HEADERS(gpgme.h,, [ 48 | echo "ERROR: You need libgpgme to build elfgpg."; 49 | AC_MSG_ERROR([Fatal: gpgme headers not found.])]) 50 | 51 | dnl Checks for typedefs, structures, and compiler characteristics. 52 | AC_C_CONST 53 | 54 | dnl Checks for library functions. 55 | AC_FUNC_VPRINTF 56 | AC_CHECK_FUNCS(strerror) 57 | 58 | 59 | AC_SUBST(ac_aux_dir) 60 | 61 | AC_OUTPUT(Makefile src/Makefile) 62 | 63 | echo \ 64 | "------------------------------------------------------------------------ 65 | Configuration: 66 | 67 | Source code location: ${srcdir} 68 | Compiler: ${CC} 69 | Compiler flags: ${CFLAGS} 70 | Host System Type: ${host} 71 | Install path: ${prefix} 72 | 73 | See config.h for further configuration information. 74 | ------------------------------------------------------------------------" 75 | 76 | 77 | -------------------------------------------------------------------------------- /lib/ep_session.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "@(#)ep_session.h 1.1 03/05/25 Bart Trojanowski " 22 | 23 | #ifndef _EP_SESSION_H 24 | #define _EP_SESSION_H 25 | 26 | typedef struct elfgpg_session_s { 27 | /* what file are we currently working on */ 28 | const char *file; 29 | int fd; 30 | 31 | /* elf processing variables */ 32 | Elf *elf; 33 | Elf32_Ehdr *ehdr; 34 | Elf32_Phdr *phdr; 35 | 36 | /* the two sections generated by elfgpg */ 37 | Elf32_Shdr *pgpsig_hdr; 38 | Elf_Scn *pgpsig_scn; 39 | Elf_Data *pgpsig_data; 40 | 41 | Elf32_Shdr *pgptab_hdr; 42 | Elf_Scn *pgptab_scn; 43 | Elf_Data *pgptab_data; 44 | } elfgpg_session_t; 45 | 46 | 47 | #endif /* _EP_SESSION_H */ 48 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2003 Bart Trojanowski 2 | # 3 | # This file is a part of the elfsign utility 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 20 | 21 | INCLUDES = -I$(top_builddir)/src -I$(top_srcdir)/src \ 22 | -I$(top_builddir)/lib -I$(top_srcdir)/lib \ 23 | -I /usr/include/libelf 24 | 25 | LIBS = -lelf -lgpgme 26 | 27 | bin_PROGRAMS = elfgpg 28 | elfgpg_SOURCES = main.c sign.c verify.c dump.c elfstrings.c 29 | EXTRA_elfgpg_SOURCES = options.h sign.h verify.h dump.h \ 30 | debug.h elfhelp.h elfgpg.h \ 31 | elfstrings.h 32 | 33 | AM_CFLAGS = -O2 -Wall -Werror 34 | #AM_CFLAGS = -O0 -ggdb -Wall -Werror 35 | 36 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_DEBUG_H 24 | #define ELFSIGN_DEBUG_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #define FATAL 0 /* errors that are not ignored */ 32 | #define ERROR 1 /* errors which can be ignored */ 33 | #define WARN 2 /* warnings that are worked around */ 34 | #define NORM 3 /* normal printed output */ 35 | #define INFO 4 /* not always needed statistics and info */ 36 | #define DEBUG 5 /* only for ppl that want to read the code */ 37 | 38 | #define ES_SHOW(lvl) \ 39 | ((lvl)<=opts->verbose) 40 | 41 | #define ES_PRINT(lvl,fmt,arg...) \ 42 | (ES_SHOW(lvl))?(fprintf(stderr,fmt,## arg)):(0) 43 | 44 | #define TODO() do{ ES_PRINT(ERROR, \ 45 | "TODO: " __FILE__ ":%d (" __PRETTY_FUNCTION__ ")\n", __LINE__); }while(0) 46 | 47 | /* include options after the macro definitions on purpose */ 48 | #include "options.h" 49 | 50 | static inline void 51 | dbg_dump_to_file( const char *fname, void* data, size_t len ) 52 | { 53 | FILE *f = fopen( fname, "w" ); 54 | fwrite( data, len, 1, f ); 55 | fclose(f); 56 | } 57 | 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/dump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "options.h" 32 | #include "verify.h" 33 | #include "elfgpg.h" 34 | #include "elfhelp.h" 35 | #include "elfstrings.h" 36 | 37 | /* there is a bit of a context for processing an elf file, this structure 38 | * saves us from using a long paramters list when calling implementation 39 | * functions */ 40 | typedef struct dump_session_s { 41 | const char *file; 42 | int fd; 43 | 44 | /* elf processing variables */ 45 | Elf *elf; 46 | 47 | Elf32_Ehdr *ehdr; 48 | Elf32_Phdr *phdr; 49 | 50 | /* the two section worth preloading */ 51 | Elf32_Shdr *pgptab_hdr, *pgpsig_hdr; 52 | Elf_Scn *pgptab_scn, *pgpsig_scn; 53 | Elf_Data *pgptab_data, *pgpsig_data; 54 | 55 | /* entry in the .pgptab */ 56 | Elf32_Pgp pgp; 57 | 58 | /* section currently processed */ 59 | Elf32_Shdr *shdr; 60 | Elf_Data *data; 61 | Elf_Scn *scn; 62 | } dump_session_t; 63 | 64 | static int 65 | init_process_elf( dump_session_t *s ) 66 | { 67 | int err; 68 | 69 | s->elf = elf_begin( s->fd, ELF_C_READ, NULL ); 70 | switch( elf_kind(s->elf) ) { 71 | case ELF_K_ELF: 72 | ES_PRINT(DEBUG, "%s: ELF file format detected\n", s->file); 73 | 74 | s->phdr = NULL; 75 | err = 1; 76 | 77 | /* get Elf Program Headers then the scn/shdr/data for the tab/sig scns */ 78 | if( !(s->ehdr = elf32_getehdr(s->elf)) ) { 79 | ES_PRINT(ERROR, "%s: %s\n", s->file, elf_errmsg(-1)); 80 | 81 | } else if ( s->ehdr->e_phnum 82 | && !(s->phdr = elf32_getphdr(s->elf)) ) { 83 | ES_PRINT(ERROR, "%s: %s\n", s->file, elf_errmsg(-1)); 84 | 85 | } else { 86 | err = 0; 87 | } 88 | 89 | /* the rest of the components are not manditory */ 90 | if ( !(s->pgptab_hdr = elf32_getshdr( s->pgptab_scn 91 | = elf_findscn(s->elf, ".pgptab"))) ) { 92 | if ( elf_errno() ) { 93 | ES_PRINT(ERROR, "%s: find .pgptab: %s\n", 94 | s->file, elf_errmsg(-1)); 95 | } 96 | 97 | } else if ( !(s->pgptab_data = elf_getdata(s->pgptab_scn, 98 | NULL)) ) { 99 | ES_PRINT(ERROR, "%s: data .pgptab: %s\n", s->file, 100 | elf_errmsg(-1)); 101 | 102 | } 103 | 104 | if ( !(s->pgpsig_hdr = elf32_getshdr( s->pgpsig_scn 105 | = elf_findscn(s->elf, ".pgpsig"))) ) { 106 | if ( elf_errno() ) { 107 | ES_PRINT(ERROR, "%s: find .pgpsig: %s\n", 108 | s->file, elf_errmsg(-1)); 109 | } 110 | 111 | } else if ( !(s->pgpsig_data = elf_getdata(s->pgpsig_scn, 112 | NULL)) ) { 113 | ES_PRINT(ERROR, "%s: data .pgpsig: %s\n", s->file, 114 | elf_errmsg(-1)); 115 | 116 | } 117 | break; 118 | 119 | case ELF_K_AR: 120 | err = 1; 121 | ES_PRINT(ERROR, "%s: elf_kind of ELF_K_AR is not supported\n", 122 | s->file); 123 | break; 124 | 125 | default: 126 | err = 1; 127 | ES_PRINT(ERROR, "%s: file format not recognized", s->file); 128 | break; 129 | } 130 | 131 | return err; 132 | } 133 | 134 | static int 135 | dump_pgpsig( dump_session_t *s ) 136 | { 137 | unsigned int max, cnt; 138 | unsigned char *bytes; 139 | 140 | if (!s->pgpsig_hdr || !s->pgpsig_scn || !s->pgpsig_data) { 141 | ES_PRINT (WARN, "%s: .pgpsig section is absent\n", 142 | s->file); 143 | goto done; 144 | } 145 | 146 | if (s->pgpsig_data->d_size < sizeof(Elf32_Pgp)) { 147 | ES_PRINT (WARN, "%s: .pgpsig section is empty\n", 148 | s->file); 149 | goto done; 150 | } 151 | 152 | ES_PRINT (NORM, "%s: .pgpsig section\n", s->file); 153 | 154 | max = s->pgpsig_data->d_size; 155 | bytes = s->pgptab_data->d_buf; 156 | 157 | ES_PRINT (NORM, " len = %d bytes\n ", max); 158 | 159 | for (cnt=1; cnt<=max; cnt++) { 160 | inline const char * separator () { 161 | if (cnt>=max) return "\n"; 162 | if ((cnt & 15) == 0) return "\n "; 163 | if ((cnt & 7) == 0) return " "; 164 | if ((cnt & 3) == 0) return " "; 165 | return " "; 166 | } 167 | ES_PRINT (NORM, "%02x%s", *(bytes++), separator()); 168 | } 169 | 170 | done: 171 | return 0; 172 | } 173 | 174 | static int 175 | dump_pgptab( dump_session_t *s ) 176 | { 177 | unsigned int max, offset, cnt; 178 | 179 | if (!s->pgptab_hdr || !s->pgptab_scn || !s->pgptab_data) { 180 | ES_PRINT (WARN, "%s: .pgptab section is absent\n", 181 | s->file); 182 | goto done; 183 | } 184 | 185 | if (s->pgptab_data->d_size < sizeof(Elf32_Pgp)) { 186 | ES_PRINT (WARN, "%s: .pgptab section is empty\n", 187 | s->file); 188 | goto done; 189 | } 190 | 191 | ES_PRINT (NORM, "%s: .pgptab section\n", s->file); 192 | 193 | ES_PRINT (NORM, " %3s %-8s %9s\n", 194 | "ndx", "entry", "size"); 195 | 196 | max = s->pgptab_data->d_size - sizeof(Elf32_Pgp); 197 | 198 | for (cnt=0, offset=0; offset<=max; cnt++, offset+=sizeof(Elf32_Pgp)) { 199 | 200 | /* compute where this pgp entry is */ 201 | Elf32_Pgp *pgp = (void*)s->pgptab_data->d_buf + offset; 202 | 203 | switch (pgp->pt_type) { 204 | case ELF_PT_SCN: 205 | ES_PRINT (NORM, " %3d SCN %-4d %9d\n", cnt, 206 | pgp->pt_shndx, 207 | pgp->pt_size); 208 | break; 209 | case ELF_PT_EHDR: 210 | ES_PRINT (NORM, " %3d EHDR %9d\n", cnt, 211 | pgp->pt_size); 212 | break; 213 | case ELF_PT_PHDR: 214 | ES_PRINT (NORM, " %3d PHDR %9d\n", cnt, 215 | pgp->pt_size); 216 | break; 217 | } 218 | 219 | } 220 | 221 | done: 222 | return 0; 223 | } 224 | 225 | static int 226 | pgptab_find_section ( dump_session_t *s, int index ) 227 | { 228 | unsigned int max, offset; 229 | 230 | if (!s->pgptab_hdr || !s->pgptab_scn || !s->pgptab_data) { 231 | return 0; 232 | } 233 | 234 | if (s->pgptab_data->d_size < sizeof(Elf32_Pgp)) { 235 | return 0; 236 | } 237 | 238 | max = s->pgptab_data->d_size - sizeof(Elf32_Pgp); 239 | 240 | for (offset = 0; offset <= max; offset += sizeof(Elf32_Pgp)) { 241 | 242 | /* compute where this pgp entry is */ 243 | Elf32_Pgp *tmp_pgp = (void*)s->pgptab_data->d_buf + offset; 244 | 245 | /* if no match continue */ 246 | if (tmp_pgp->pt_shndx != index) 247 | continue; 248 | 249 | /* if we match get the data from the table and return */ 250 | memcpy( &s->pgp, tmp_pgp, sizeof(Elf32_Pgp) ); 251 | return 1; 252 | } 253 | 254 | return 0; 255 | } 256 | 257 | static int 258 | dump_elf( dump_session_t *s ) 259 | { 260 | int ret=-1; 261 | 262 | ES_PRINT (NORM, "%s: ELF section summary\n", s->file); 263 | ES_PRINT (NORM, " %3s %-13s %-9s %-10s %s\n", 264 | "scn", "type", "size", "test", "name"); 265 | 266 | /* */ 267 | s->scn = NULL; 268 | while ((s->shdr = elf32_getshdr ( 269 | s->scn = elf_nextscn (s->elf, s->scn)))) { 270 | 271 | int found, ndx; 272 | Elf32_Word type, size; 273 | const char *tname, *sname; 274 | char type_number[16], test_result[32]; 275 | 276 | /* this is the index of this section */ 277 | ndx = elf_ndxscn(s->scn); 278 | 279 | /* get the string of the type of this entry */ 280 | type = s->shdr->sh_type; 281 | tname = elf_sht_string (type); 282 | /* if the type name is unknown print the hex number */ 283 | if (!tname) { 284 | tname = type_number; 285 | sprintf (type_number, "0x%08x", type); 286 | } 287 | 288 | /* get the string name of the section */ 289 | sname = elf_strptr (s->elf, s->ehdr->e_shstrndx, 290 | s->shdr->sh_name); 291 | 292 | /* get the data structure, for the length */ 293 | s->data = elf_getdata (s->scn, NULL); 294 | size = s->data?s->data->d_size:0; 295 | 296 | /* locate the section in the .pgptab table */ 297 | found = pgptab_find_section (s, ndx); 298 | if (!found) { 299 | strcpy (test_result, "-"); 300 | } else if (s->pgp.pt_type != ELF_PT_SCN) { 301 | snprintf (test_result, 31, "type!=SCN"); 302 | } else if (s->pgp.pt_size != size) { 303 | snprintf (test_result, 31, "size!=%d", s->pgp.pt_size); 304 | } else { 305 | strcpy (test_result, "OK"); 306 | } 307 | 308 | /* print what we know */ 309 | ES_PRINT (NORM, " %3d %-13s %-9d %-10s %s\n", ndx, 310 | tname, size, test_result, sname?sname:""); 311 | } 312 | 313 | ret=0; 314 | 315 | return ret; 316 | } 317 | 318 | 319 | int 320 | do_elfdump( const char *file, int fd ) 321 | { 322 | int ret; 323 | dump_session_t session; 324 | 325 | ES_PRINT(DEBUG,"elfdump( '%s', %d )...\n" 326 | "\tverbose = %d\n" 327 | "\tforce = %d\n" 328 | "\tkeyname = %s\n" 329 | "\tkeyring = %s\n" 330 | "\talgname = %s\n", 331 | file, fd, 332 | opts->verbose, opts->force, opts->keyname, 333 | opts->keyring, opts->algname ); 334 | 335 | memset(&session, 0, sizeof(dump_session_t)); 336 | session.file = file; 337 | session.fd = fd; 338 | 339 | ret = init_process_elf( &session ); 340 | 341 | if( ! ret ) 342 | ret = dump_pgptab( &session ); 343 | 344 | if( ! ret ) 345 | ret = dump_pgpsig( &session ); 346 | 347 | if( ! ret ) 348 | ret = dump_elf( &session ); 349 | 350 | elf_end(session.elf); 351 | 352 | return ret; 353 | } 354 | 355 | -------------------------------------------------------------------------------- /src/dump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_DUMP_H 24 | #define ELFSIGN_DUMP_H 25 | 26 | int do_elfdump( const char *name, int fd ); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/elfgpg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFPGP_H 24 | #define ELFPGP_H 25 | 26 | #include 27 | 28 | /* new sections that will be used by elfgpg */ 29 | 30 | #define SHT_PGPTAB (SHT_LOUSER|('p'<<16)|('g'<<8)|'p') 31 | #define SHT_PGPSIG SHT_PGPTAB+1 32 | 33 | /* .pgptab entry types */ 34 | #define ELF_PT_EHDR 0 35 | #define ELF_PT_PHDR 1 36 | #define ELF_PT_SCN 2 37 | 38 | /* .pgptab entry structure */ 39 | typedef struct 40 | { 41 | Elf32_Word pt_type; /* Type of pgp table entry */ 42 | Elf32_Word pt_size; /* Symbol size */ 43 | Elf32_Section pt_shndx; /* Section index */ 44 | } Elf32_Pgp; 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/elfhelp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_ELFHELP_H 24 | #define ELFSIGN_ELFHELP_H 25 | 26 | #include 27 | #include 28 | #include "debug.h" 29 | 30 | /* 31 | * create_data() and create_section() was taken from libelf-examples-0.1.0 32 | * Copyright (C) 1997 Michael Riepe 33 | */ 34 | 35 | static Elf_Data* create_data(Elf_Scn *scn, void *buf, size_t size, 36 | Elf_Type type, size_t align) __attribute__ ((unused)); 37 | static Elf_Scn* create_section(Elf *elf, unsigned type, char *name) 38 | __attribute__ ((unused)); 39 | 40 | #define elferr(str) fprintf(stderr, "%s: %s\n", str, elf_errmsg(-1)) 41 | 42 | static Elf_Data* 43 | create_data(Elf_Scn *scn, void *buf, size_t size, Elf_Type type, size_t align) 44 | { 45 | Elf_Data *data; 46 | 47 | if ((data = elf_newdata(scn))) { 48 | data->d_align = align; 49 | data->d_size = size; 50 | data->d_type = type; 51 | data->d_buf = buf; 52 | return data; 53 | } 54 | 55 | ES_PRINT(ERROR, "%s: elf_newdata(scn=%p,buf=%p,size=%"PRIuMAX",type=%u," 56 | "align=%"PRIuMAX"): %s\n", __PRETTY_FUNCTION__, scn, 57 | buf, size, type, align, elf_errmsg(-1)); 58 | return NULL; 59 | } 60 | 61 | static Elf_Scn* 62 | create_section(Elf *elf, unsigned type, char *name) 63 | { 64 | static char shstrtab[] = ".shstrtab"; 65 | Elf32_Ehdr *ehdr; 66 | Elf32_Shdr *shdr; 67 | Elf_Data *data; 68 | Elf_Scn *scn, *strscn; 69 | 70 | if (!(ehdr = elf32_getehdr(elf))) { 71 | ES_PRINT(ERROR, "%s: elf32_getehdr(%p): %s\n", 72 | __PRETTY_FUNCTION__, elf, elf_errmsg(-1)); 73 | return NULL; 74 | } 75 | if (!ehdr->e_shstrndx) { 76 | ehdr->e_version = EV_CURRENT; 77 | if (!(shdr = elf32_getshdr(strscn = elf_newscn(elf)))) { 78 | ES_PRINT(ERROR, "%s: elf32_getshdr(%p): %s\n", 79 | __PRETTY_FUNCTION__, elf, elf_errmsg(-1)); 80 | return NULL; 81 | } 82 | shdr->sh_type = SHT_STRTAB; 83 | ehdr->e_shstrndx = elf_ndxscn(strscn); 84 | if (!create_data(strscn, "", 1, ELF_T_BYTE, 1)) { 85 | return NULL; 86 | } 87 | if (!(data = create_data(strscn, shstrtab, sizeof(shstrtab), 88 | ELF_T_BYTE, 1))) { 89 | return NULL; 90 | } 91 | if (elf_update(elf, ELF_C_NULL) == -1) { 92 | ES_PRINT(ERROR, "%s: elf_update(%p,ELF_C_NULL): %s\n", 93 | __PRETTY_FUNCTION__, elf, elf_errmsg(-1)); 94 | return NULL; 95 | } 96 | shdr->sh_name = data->d_off; 97 | } 98 | else if (!(strscn = elf_getscn(elf, ehdr->e_shstrndx))) { 99 | ES_PRINT(ERROR, "%s: elf_getscn(%p,%u): %s\n", 100 | __PRETTY_FUNCTION__, elf, ehdr->e_shstrndx, 101 | elf_errmsg(-1)); 102 | return NULL; 103 | } 104 | if (!(shdr = elf32_getshdr(scn = elf_newscn(elf)))) { 105 | ES_PRINT(ERROR, "%s: elf32_getshdr(%p): %s\n", 106 | __PRETTY_FUNCTION__, elf, elf_errmsg(-1)); 107 | return NULL; 108 | } 109 | if (!(data = create_data(strscn, name, 1 + strlen(name), 110 | ELF_T_BYTE, 1))) { 111 | return NULL; 112 | } 113 | if (elf_update(elf, ELF_C_NULL) == -1) { 114 | ES_PRINT(ERROR, "%s: elf_update(%p,ELF_C_NULL): %s\n", 115 | __PRETTY_FUNCTION__, elf, elf_errmsg(-1)); 116 | return NULL; 117 | } 118 | shdr->sh_name = data->d_off; 119 | shdr->sh_type = type; 120 | return scn; 121 | } 122 | 123 | static Elf_Scn* 124 | elf_findscn(Elf *elf, const char *name) 125 | { 126 | Elf32_Ehdr *ehdr; 127 | Elf32_Shdr *shdr; 128 | Elf_Scn *scn; 129 | char *str; 130 | 131 | if ((ehdr = elf32_getehdr(elf))) { 132 | scn = NULL; 133 | while ((shdr = elf32_getshdr(scn = elf_nextscn(elf, scn)))) { 134 | if (shdr->sh_type == SHT_NULL) { 135 | continue; 136 | } 137 | if (!(str = elf_strptr(elf, ehdr->e_shstrndx, 138 | shdr->sh_name))) { 139 | break; 140 | } 141 | if (!strcmp(str, name)) { 142 | return scn; 143 | } 144 | } 145 | } 146 | return NULL; 147 | } 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/elfstrings.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #include 24 | #include "debug.h" 25 | 26 | const char * 27 | elf_sht_string (int sh_type) 28 | { 29 | if (sh_type == SHT_NULL) return "NULL"; 30 | if (sh_type == SHT_PROGBITS) return "PROGBITS"; 31 | if (sh_type == SHT_SYMTAB) return "SYMTAB"; 32 | if (sh_type == SHT_STRTAB) return "STRTAB"; 33 | if (sh_type == SHT_RELA) return "RELA"; 34 | if (sh_type == SHT_HASH) return "HASH"; 35 | if (sh_type == SHT_DYNAMIC) return "DYNAMIC"; 36 | if (sh_type == SHT_NOTE) return "NOTE"; 37 | if (sh_type == SHT_NOBITS) return "NOBITS"; 38 | if (sh_type == SHT_REL) return "REL"; 39 | if (sh_type == SHT_SHLIB) return "SHLIB"; 40 | if (sh_type == SHT_DYNSYM) return "DYNSYM"; 41 | if (sh_type == SHT_INIT_ARRAY) return "INIT_ARRAY"; 42 | if (sh_type == SHT_FINI_ARRAY) return "FINI_ARRAY"; 43 | if (sh_type == SHT_PREINIT_ARRAY) return "PREINIT_ARRAY"; 44 | if (sh_type == SHT_GROUP) return "GROUP"; 45 | if (sh_type == SHT_SYMTAB_SHNDX) return "SYMTAB_SHNDX"; 46 | if (sh_type == SHT_NUM) return "NUM"; 47 | if (sh_type == SHT_LOOS) return "LOOS"; 48 | if (sh_type == SHT_GNU_LIBLIST) return "GNU_LIBLIST"; 49 | if (sh_type == SHT_CHECKSUM) return "CHECKSUM"; 50 | if (sh_type == SHT_LOSUNW) return "LOSUNW"; 51 | if (sh_type == SHT_SUNW_move) return "SUNW_move"; 52 | if (sh_type == SHT_SUNW_COMDAT) return "SUNW_COMDAT"; 53 | if (sh_type == SHT_SUNW_syminfo) return "SUNW_syminfo"; 54 | if (sh_type == SHT_GNU_verdef) return "GNU_verdef"; 55 | if (sh_type == SHT_GNU_verneed) return "GNU_verneed"; 56 | if (sh_type == SHT_GNU_versym) return "GNU_versym"; 57 | if (sh_type == SHT_HISUNW) return "HISUNW"; 58 | if (sh_type == SHT_HIOS) return "HIOS"; 59 | if (sh_type == SHT_LOPROC) return "LOPROC"; 60 | if (sh_type == SHT_HIPROC) return "HIPROC"; 61 | if (sh_type == SHT_LOUSER) return "LOUSER"; 62 | if (sh_type == SHT_HIUSER) return "HIUSER"; 63 | 64 | return NULL; 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/elfstrings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 by SOMA Networks, Inc. 3 | * All rights reserved. 4 | * 5 | * This material is proprietary to SOMA Networks, Inc. and, 6 | * in addition to the above mentioned Copyright, may be 7 | * subject to protection under other intellectual property 8 | * regimes, including patents, trade secrets, designs and/or 9 | * trademarks. 10 | * 11 | * Any use of this material for any purpose, except with an 12 | * express license from SOMA Networks, Inc. is strictly 13 | * prohibited. 14 | */ 15 | 16 | #ident "@(#)ccommenter.vim 1.3 03/02/27 SOMA Networks" 17 | 18 | #ifndef ELFSIGN_ELFSTRINGS_H 19 | #define ELFSIGN_ELFSTRINGS_H 20 | 21 | /* converts an elf section header type to a string of it's name */ 22 | extern const char * elf_sht_string (int sh_type); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #define COPYRIGHT "(C) 2001-2003 Bart Trojanowski " 24 | 25 | #define _GNU_SOURCE 26 | 27 | #include "config.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include "debug.h" 41 | #include "options.h" 42 | #include "sign.h" 43 | #include "verify.h" 44 | #include "dump.h" 45 | 46 | elfsign_options_t *opts; 47 | 48 | static struct option long_options[12] = 49 | { 50 | {"sign", 0, 0, 's'}, 51 | {"verify", 0, 0, 'c'}, 52 | {"dump", 0, 0, 'd'}, 53 | {"quiet", 0, 0, 'q'}, 54 | {"verbose", 0, 0, 'v'}, 55 | {"force", 0, 0, 'f'}, 56 | {"version", 0, 0, 'V'}, 57 | {"help", 0, 0, 'h'}, 58 | {"key", 1, 0, 'k'}, 59 | {"keyring", 1, 0, 'r'}, 60 | {"algname", 1, 0, 'a'}, 61 | {0,0,0,0} 62 | }; 63 | 64 | static int 65 | dump_version( void ) 66 | { 67 | printf(PACKAGE " v" VERSION " - " COPYRIGHT"\n"); 68 | return 0; 69 | } 70 | 71 | static int 72 | dump_help( const char * name ) 73 | { 74 | printf(PACKAGE " v" VERSION " - " COPYRIGHT"\n"); 75 | printf("\nSyntax: %s [command] [options] file(s)\n", name); 76 | printf("\ncommands:\n" 77 | " -s, --sign append or replace signature\n" 78 | " -c, --verify verify signature\n" 79 | " -d, --dump list signature info\n" 80 | " -h, --help what you are reading now\n" 81 | " -V, --version print version info\n" 82 | "\noptions:\n" 83 | " -q, --quiet be more quiet\n" 84 | " -v, --verbose be more verbose\n" 85 | " -f, --force ignore some errors\n" 86 | " -k, --key specify a key to use\n" 87 | " -r, --keyring specify the location of the keyring\n" 88 | " -a, --algname specify the algorithm for hashing\n" 89 | ); 90 | return 0; 91 | } 92 | 93 | static int 94 | process_options( int argc, char *const *argv ) 95 | { 96 | int ret, len; 97 | 98 | ES_PRINT(DEBUG,"Processing options...\n"); 99 | 100 | len = strlen(argv[0]); 101 | if( len>=7 && strncmp( argv[0]+len-7, "elfsign", 8 ) == 0 ) { 102 | ES_PRINT(DEBUG,"operation = SIGN\n"); 103 | opts->operation = SIGN; 104 | 105 | } else if( len>=8 && strncmp( argv[0]+len-8, "elfverify", 10 ) == 0 ) { 106 | ES_PRINT(DEBUG,"operation = VERIFY\n"); 107 | opts->operation = VERIFY; 108 | 109 | } 110 | 111 | ret=1; 112 | for(;;) { 113 | int c, option_index; 114 | 115 | c = getopt_long ( argc, (char * const *)argv, "scqvfVhk:r:a:", 116 | long_options, &option_index ); 117 | 118 | switch( c ) { 119 | case 's': 120 | opts->operation = SIGN; 121 | ES_PRINT(DEBUG,"operation = SIGN\n"); 122 | break; 123 | 124 | case 'c': 125 | opts->operation = VERIFY; 126 | ES_PRINT(DEBUG,"operation = VERIFY\n"); 127 | break; 128 | 129 | case 'd': 130 | opts->operation = DUMP; 131 | ES_PRINT(DEBUG,"operation = DUMP\n"); 132 | break; 133 | 134 | case 'q': 135 | opts->verbose --; 136 | ES_PRINT(DEBUG,"verbosity lowered (%d)\n", 137 | opts->verbose); 138 | break; 139 | 140 | case 'v': 141 | opts->verbose ++; 142 | ES_PRINT(DEBUG,"verbosity raised (%d)\n", 143 | opts->verbose); 144 | break; 145 | 146 | case 'f': 147 | opts->force = 1; 148 | ES_PRINT(DEBUG,"force flag set\n"); 149 | break; 150 | 151 | case 'V': 152 | ES_PRINT(DEBUG,"version requested\n"); 153 | dump_version(); 154 | exit(0); 155 | break; 156 | 157 | case 'h': 158 | ES_PRINT(DEBUG,"help requested\n"); 159 | dump_help(argv[0]); 160 | exit(0); 161 | break; 162 | 163 | case 'k': 164 | ES_PRINT(DEBUG,"keyname set to %s\n",optarg); 165 | opts->keyname = optarg; 166 | break; 167 | 168 | case 'r': 169 | ES_PRINT(DEBUG,"keyring set to %s\n",optarg); 170 | opts->keyring = optarg; 171 | break; 172 | 173 | case 'a': 174 | ES_PRINT(DEBUG,"algorithm set to %s\n",optarg); 175 | opts->algname = optarg; 176 | break; 177 | 178 | default: 179 | goto scan_finished; 180 | } 181 | 182 | /* count number of processed options */ 183 | ret = optind; 184 | } 185 | 186 | scan_finished: 187 | ES_PRINT(DEBUG,"option scan complete, rest should be files.\n"); 188 | 189 | if( opts->operation == NONE ) { 190 | ES_PRINT(ERROR,"Need to specify --sign or --verify " 191 | "operation\n"); 192 | return -1; 193 | } 194 | 195 | return ret; 196 | } 197 | 198 | int 199 | test_file( const char *file, int fd, int mode ) 200 | { 201 | static int uid=-1, gid, euid, egid; 202 | int ret=-1; 203 | struct stat st; 204 | 205 | ES_PRINT(DEBUG,"testing file %s\n",file); 206 | 207 | if(uid==-1) { 208 | uid = getuid(); 209 | gid = getgid(); 210 | euid = geteuid(); 211 | egid = getegid(); 212 | } 213 | 214 | errno=0; 215 | if( ( ret = fstat(fd, &st) ) ) { 216 | ES_PRINT(ERROR,"%s: %s\n", file, strerror(errno)); 217 | if( !opts->force ) goto bail; 218 | 219 | } else { 220 | /* fail on the next goto bail */ 221 | ret = -1; 222 | 223 | if( !( st.st_mode & S_IFREG ) ) { 224 | ES_PRINT(ERROR,"%s: not a regular file\n", file); 225 | if( !opts->force ) goto bail; 226 | 227 | } else if( !( euid == 0 ) ) { 228 | /* test to see if this file can be read/written 229 | * by us */ 230 | int good = 0; 231 | 232 | if( st.st_uid == uid || st.st_uid == euid ) { 233 | /* user mode required */ 234 | unsigned int um = mode << 6; 235 | ES_PRINT(DEBUG,"%s: testing owner\n",file); 236 | if( (st.st_mode & um) == um ) 237 | good++; 238 | } 239 | 240 | if( st.st_gid == gid || st.st_gid == egid ) { 241 | /* group mode required */ 242 | unsigned int gm = mode << 3; 243 | ES_PRINT(DEBUG,"%s: testing group\n",file); 244 | if( (st.st_mode & gm) == gm ) 245 | good++; 246 | } 247 | 248 | if( !good ) { 249 | /* other mode required */ 250 | unsigned int om = mode; 251 | ES_PRINT(DEBUG,"%s: testing other\n",file); 252 | if( (st.st_mode & om) == om ) 253 | good++; 254 | } 255 | 256 | if( !good ) { 257 | ES_PRINT(ERROR, "%s: insufficien access " 258 | "on file\n", file); 259 | if( !opts->force ) goto bail; 260 | } 261 | } 262 | } 263 | 264 | ret = 0; 265 | 266 | bail: 267 | return ret; 268 | } 269 | 270 | int 271 | main( int argc, char **argv ) 272 | { 273 | int i, ret, t_mode, o_mode, first, count; 274 | elfsign_options_t local_options; 275 | int(*proc_fn)(const char* name, int fd); 276 | 277 | ret = 0; 278 | if( argc == 1 ) { 279 | dump_help(argv[0]); 280 | goto bail; 281 | } 282 | 283 | /* initialize the global reference */ 284 | opts = &local_options; 285 | init_options(); 286 | 287 | ret = 1; 288 | first = process_options(argc, argv); 289 | if( first<=0 ) goto bail; 290 | 291 | switch( opts->operation ) { 292 | case SIGN: 293 | o_mode = O_RDWR; 294 | t_mode = S_IROTH|S_IWOTH; 295 | proc_fn = do_elfsign; 296 | break; 297 | 298 | case VERIFY: 299 | o_mode = O_RDONLY; 300 | t_mode = S_IROTH; 301 | proc_fn = do_elfverify; 302 | break; 303 | 304 | case DUMP: 305 | o_mode = O_RDONLY; 306 | t_mode = S_IROTH; 307 | proc_fn = do_elfdump; 308 | break; 309 | 310 | default: 311 | ret = EINVAL; 312 | goto bail; 313 | } 314 | 315 | count = argc - first; 316 | if( count <= 0 ) { 317 | ES_PRINT(ERROR,"no files specified to %s\n", 318 | (opts->operation==SIGN)?"sign":"verify"); 319 | ret = ENOENT; 320 | goto bail; 321 | } 322 | 323 | if (elf_version(EV_CURRENT) == EV_NONE) { 324 | ES_PRINT(ERROR, "%s: %s\n", argv[0], elf_errmsg(-1)); 325 | } 326 | 327 | ES_PRINT(DEBUG,"processing %d files...\n",count); 328 | for(i=0;ifile_name_max < file_name_len ) 334 | opts->file_name_max = file_name_len; 335 | } 336 | opts->file_name_max += 2; 337 | 338 | for(i=0;i 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_OPTIONS_H 24 | #define ELFSIGN_OPTIONS_H 25 | 26 | #include 27 | #include 28 | 29 | #include "debug.h" 30 | 31 | typedef struct elfsign_options_s { 32 | 33 | enum { NONE=0, SIGN, VERIFY, DUMP } operation; 34 | 35 | /* debug level */ 36 | int verbose; 37 | 38 | /* force through some errors */ 39 | int force; 40 | 41 | /* maximum width of a file name */ 42 | int file_name_max; 43 | 44 | /* what key to use */ 45 | char *keyname; 46 | 47 | /* what keyring to use */ 48 | char *keyring; 49 | 50 | /* algorithm for signing */ 51 | char *algname; 52 | 53 | 54 | } elfsign_options_t; 55 | 56 | extern elfsign_options_t *opts; 57 | 58 | static inline void 59 | init_options( void ) 60 | { 61 | opts->operation = NONE; 62 | opts->verbose = NORM; 63 | opts->force = 0; 64 | opts->file_name_max = 10; 65 | opts->keyname = NULL; 66 | opts->keyring = NULL; 67 | opts->algname = NULL; 68 | } 69 | 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/sign.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "options.h" 33 | #include "sign.h" 34 | #include "elfgpg.h" 35 | #include "elfhelp.h" 36 | #include "elfstrings.h" 37 | 38 | typedef struct sign_session_s 39 | { 40 | /* current read state */ 41 | u_int32_t tab_index; 42 | u_int32_t scn_offset; 43 | int read_cb_eof; 44 | 45 | /* file being processed */ 46 | const char *file; 47 | int fd; 48 | gpgme_ctx_t gpgme_ctx; 49 | 50 | void *pgptab_head; /* allocated buffer start */ 51 | void *pgptab_tail; /* points to next byte to be used */ 52 | size_t pgptab_len; /* lenght of the allocated buffer */ 53 | 54 | /* the .pgptab and .pgpsig sections, headers and data */ 55 | Elf_Scn *pgptab_scn, *pgpsig_scn; 56 | Elf_Data *pgptab_data, *pgpsig_data; 57 | Elf_Data fake_data; 58 | 59 | /* entry in the .pgptab */ 60 | Elf32_Pgp pgp; 61 | 62 | /* processing variables */ 63 | Elf *elf; 64 | 65 | Elf32_Ehdr *ehdr; 66 | Elf32_Phdr *phdr; 67 | 68 | Elf32_Shdr *shdr; 69 | Elf_Data *data; 70 | Elf_Scn *scn; 71 | 72 | /* had to generate the new sections */ 73 | int new_sections; 74 | 75 | /* the signature buffer */ 76 | size_t slen; 77 | char sig[4096]; 78 | } 79 | sign_session_t; 80 | 81 | static int 82 | linelen (const char *s) 83 | { 84 | int i; 85 | for (i = 0; *s && *s != '\n'; s++, i++) 86 | ; 87 | return i; 88 | } 89 | 90 | 91 | static char pass[1024] = {0,}; 92 | 93 | static gpgme_error_t 94 | passphrase_cb (void *hook, const char *uid_hint, const char *passphrase_info, 95 | int prev_was_bad, int fd) 96 | { 97 | struct termios term; 98 | static struct termios termsave; 99 | const char *cmd=NULL, *uid=NULL, *info=NULL; 100 | 101 | fprintf(stderr, "%s: uid_hint = %s\n", __FUNCTION__, uid_hint); 102 | fprintf(stderr, "%s: passphrase_info = %s\n", __FUNCTION__, passphrase_info); 103 | 104 | if( !passphrase_info ) { 105 | /* this is the second callback meant for releasing 106 | * resources, but we want to keep it to the very end of 107 | * the signing process */ 108 | return GPG_ERR_CANCELED; 109 | } 110 | 111 | ES_PRINT(DEBUG,"%s: getting password\n", __PRETTY_FUNCTION__); 112 | 113 | /* get the description parts 114 | * [ code borowed from Sylpheed; thanks to Werner Koch ] 115 | */ 116 | cmd = passphrase_info; 117 | uid = strchr (cmd, '\n'); 118 | if (uid) { 119 | info = strchr (++uid, '\n'); 120 | if (info ) 121 | info++; 122 | } 123 | 124 | if (!uid) 125 | uid = "[no user id]"; 126 | if (!info) 127 | info = ""; 128 | 129 | /* now figure out if this is a retry or first attempt */ 130 | if( strncmp(cmd,"TRY_AGAIN",9)==0 ) { 131 | fprintf(stderr, "Bad passphrase! Try again...\n\n"); 132 | pass[0] = 0; 133 | 134 | }else if( strncmp(cmd,"ENTER",5)==0 ) { 135 | if( pass[0] ) { 136 | goto return_password; 137 | } 138 | } 139 | 140 | /* must get a password... */ 141 | fprintf(stderr, "Key Id: %.*s\n", linelen(uid), uid); 142 | fprintf(stderr, "Info: %.*s\n", linelen(info), info); 143 | fprintf(stderr, "Enter passphrase:"); 144 | fflush(stderr); 145 | 146 | /* disable echo */ 147 | if( tcgetattr(fileno(stdin), &termsave) ) { 148 | ES_PRINT(ERROR,"tcgetattr() failed: %s\n", strerror(errno) ); 149 | return GPG_ERR_CANCELED; 150 | } 151 | term = termsave; 152 | term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 153 | if( tcsetattr( fileno(stdin), TCSAFLUSH, &term ) ) { 154 | ES_PRINT(ERROR,"tcsetattr() failed: %s\n", strerror(errno) ); 155 | return GPG_ERR_CANCELED; 156 | } 157 | 158 | /* get the string */ 159 | if( !fgets(pass, sizeof(pass)-1, stdin) ) { 160 | ES_PRINT(ERROR,"passphrase_cb: %s\n",strerror(errno)); 161 | return GPG_ERR_CANCELED; 162 | } 163 | 164 | /* reset echo */ 165 | if( tcsetattr(fileno(stdin), TCSAFLUSH, &termsave) ) { 166 | ES_PRINT(ERROR,"tcsetattr() failed: %s\n", strerror(errno) ); 167 | return GPG_ERR_CANCELED; 168 | } 169 | 170 | fprintf(stderr, "\n"); 171 | 172 | return_password: 173 | if (write(fd, pass, strlen(pass)) < 0) 174 | return GPG_ERR_CANCELED; 175 | return GPG_ERR_NO_ERROR; 176 | } 177 | 178 | static int 179 | configure_gpg( gpgme_ctx_t *ctx ) 180 | { 181 | gpgme_error_t err; 182 | 183 | ES_PRINT(DEBUG,"%s: gpgme configuration\n", __PRETTY_FUNCTION__); 184 | 185 | err = gpgme_new(ctx); 186 | if( err ) { 187 | ES_PRINT(ERROR, "gpgme_new: %s\n", gpgme_strerror(err)); 188 | return -1; 189 | } 190 | 191 | if ( !getenv("GPG_AGENT_INFO") ) 192 | gpgme_set_passphrase_cb ( *ctx, passphrase_cb, NULL ); 193 | 194 | gpgme_set_textmode(*ctx,1); 195 | gpgme_set_armor(*ctx,0); 196 | 197 | return 0; 198 | } 199 | 200 | 201 | static int 202 | pgptab_add( sign_session_t *s, Elf32_Pgp *p ) 203 | { 204 | int err = 0; 205 | char *name = ""; 206 | 207 | ES_PRINT(DEBUG,"%s: inserting pgptab entry\n", __PRETTY_FUNCTION__); 208 | 209 | if( p->pt_type == ELF_PT_SCN ) 210 | if( !(name = elf_strptr(s->elf, s->ehdr->e_shstrndx, 211 | s->shdr->sh_name)) ) 212 | name = ""; 213 | 214 | ES_PRINT(DEBUG, "pgptab_add: '%s' [%s/%d/%d]\n", 215 | name, 216 | (p->pt_type == ELF_PT_EHDR)?"EHDR" 217 | :((p->pt_type == ELF_PT_PHDR)?"PHDR" 218 | :((p->pt_type == ELF_PT_SCN)?"SCN":"???")), 219 | p->pt_size, p->pt_shndx); 220 | 221 | if( !s->pgptab_head ) { 222 | s->pgptab_len = 1024; 223 | s->pgptab_head = (void*)malloc( s->pgptab_len ); 224 | if( !s->pgptab_head ) { 225 | ES_PRINT(ERROR, "pgptab_add: %s\n", strerror(errno)); 226 | err = 1; 227 | goto bail; 228 | } 229 | s->pgptab_tail = s->pgptab_head; 230 | } 231 | 232 | if( ( s->pgptab_tail + sizeof(Elf32_Pgp) ) > 233 | ( s->pgptab_head + s->pgptab_len ) ) { 234 | void *oldbuf = s->pgptab_head; 235 | size_t newlen = s->pgptab_len * 2; 236 | void *newbuf = (void*)malloc( newlen ); 237 | if( !newbuf ) { 238 | ES_PRINT(ERROR, "pgptab_add: %s\n", strerror(errno)); 239 | err = 1; 240 | goto bail; 241 | } 242 | 243 | memcpy( newbuf, oldbuf, s->pgptab_len ); 244 | s->pgptab_head = newbuf; 245 | free(oldbuf); 246 | } 247 | 248 | memcpy( s->pgptab_tail, p, sizeof( Elf32_Pgp ) ); 249 | s->pgptab_tail += sizeof( Elf32_Pgp ); 250 | 251 | bail: 252 | return err; 253 | } 254 | 255 | static ssize_t elf_data_read (void* opaque, void *buff, size_t blen); 256 | static struct gpgme_data_cbs elf_data = { 257 | .read = elf_data_read, 258 | .write = NULL, 259 | .seek = NULL, 260 | .release = NULL, 261 | }; 262 | 263 | static ssize_t 264 | elf_data_read (void* opaque, void *buff, size_t blen) 265 | { 266 | sign_session_t *s = (void*)opaque; 267 | int eof; /* 1 if there is no more data to read */ 268 | void *src_ptr, *dst_ptr; 269 | size_t src_len, dst_len; 270 | const char *tname, *sname; 271 | char type_number[16]; 272 | int ndx; 273 | 274 | ES_PRINT(DEBUG, "%s(%p, %p, %"PRIuMAX")\n", 275 | __PRETTY_FUNCTION__, opaque, buff, blen); 276 | 277 | dst_ptr = buff; 278 | dst_len = blen; 279 | 280 | if( (eof = s->read_cb_eof) ) 281 | goto bail; 282 | 283 | more: 284 | if( !s->scn_offset ) { 285 | /* means that we need to fetch the next pgp entry from 286 | * .pgptab */ 287 | long pgp_offset = s->tab_index * sizeof(Elf32_Pgp); 288 | 289 | ES_PRINT(DEBUG, "read_elf_cb: !offset: new section %d\n", 290 | s->tab_index); 291 | 292 | if( (pgp_offset+sizeof(Elf32_Pgp)) > s->pgptab_data->d_size ) { 293 | ES_PRINT(DEBUG,"%s: got to the end of .pgptab\n", 294 | s->file); 295 | s->read_cb_eof = 1; 296 | goto bail; 297 | 298 | } 299 | memcpy( &s->pgp, s->pgptab_data->d_buf + pgp_offset, 300 | sizeof(Elf32_Pgp) ); 301 | 302 | ES_PRINT(DEBUG, "read_elf_cb: pgptab[%d] = { %d, %d, %d }\n", 303 | s->tab_index, s->pgp.pt_type, s->pgp.pt_size, 304 | s->pgp.pt_shndx); 305 | 306 | switch( s->pgp.pt_type ) { 307 | case ELF_PT_EHDR: 308 | /* we got an elf header */ 309 | s->data = &s->fake_data; 310 | s->data->d_buf = (void*)s->ehdr; 311 | s->data->d_size = s->pgp.pt_size; 312 | 313 | ES_PRINT(INFO," %-7s %-13s %5d %s\n", 314 | "EHDR", "", s->pgp.pt_size, ""); 315 | break; 316 | 317 | case ELF_PT_PHDR: 318 | /* get got a program header */ 319 | s->data = &s->fake_data; 320 | s->data->d_buf = (void*)s->phdr; 321 | s->data->d_size = s->pgp.pt_size; 322 | 323 | ES_PRINT(INFO," %-7s %-13s %5d %s\n", 324 | "PHDR", "", s->pgp.pt_size, ""); 325 | break; 326 | 327 | case ELF_PT_SCN: 328 | /* this is the section index */ 329 | ndx = s->pgp.pt_shndx; 330 | 331 | /* we know the section number, get the section & header */ 332 | s->scn = elf_getscn(s->elf, ndx); 333 | if( !(s->shdr = elf32_getshdr(s->scn)) ) { 334 | ES_PRINT(ERROR,"%s: shndx=%d: %s\n", s->file, 335 | ndx, elf_errmsg(-1)); 336 | eof = s->read_cb_eof = 1; 337 | goto bail; 338 | } 339 | 340 | /* make sure we have a type for this section */ 341 | tname = elf_sht_string (s->shdr->sh_type); 342 | if (!tname) { 343 | tname = type_number; 344 | sprintf (type_number, "0x%08x", 345 | s->shdr->sh_type); 346 | } 347 | 348 | /* get the name of the elf section we are looking at */ 349 | sname = elf_strptr(s->elf, s->ehdr->e_shstrndx, 350 | s->shdr->sh_name); 351 | 352 | /* now get the data for that section */ 353 | if( !(s->data = elf_getdata(s->scn, NULL)) ) { 354 | ES_PRINT(ERROR,"%s: get data %s\n", s->file, 355 | elf_errmsg(-1)); 356 | eof = s->read_cb_eof = 1; 357 | goto bail; 358 | } 359 | 360 | ES_PRINT(INFO," SCN %-3d %-13s %5"PRIuMAX" %s\n", 361 | ndx, tname, s->data->d_size, sname); 362 | break; 363 | 364 | default: 365 | ES_PRINT(ERROR,"%s: invalid .pgptab entry type " 366 | "at index %d\n", 367 | s->file, s->pgp.pt_shndx); 368 | eof = s->read_cb_eof = 1; 369 | goto bail; 370 | } 371 | } 372 | 373 | src_ptr = s->data->d_buf + s->scn_offset; 374 | src_len = s->data->d_size - s->scn_offset; 375 | if( !src_len ) 376 | goto bail; 377 | 378 | ES_PRINT(DEBUG,"read_elf_cb: have data @ %p of len %"PRIuMAX" bytes\n", 379 | src_ptr, src_len); 380 | 381 | /* test to see if all the current data block can be submitted */ 382 | if( src_len <= dst_len ) { 383 | if (s->data->d_buf) { 384 | /* if we have a src pointer then copy */ 385 | memcpy ( dst_ptr, src_ptr, src_len ); 386 | } else { 387 | /* otherwise we clear -- probably a .bss section */ 388 | memset ( dst_ptr, 0, src_len ); 389 | } 390 | /* move buffer pointer/size to after new addition */ 391 | dst_ptr += src_len; 392 | dst_len -= src_len; 393 | /* prep for next call */ 394 | s->scn_offset = 0; 395 | s->tab_index ++; 396 | 397 | if( !s->read_cb_eof && dst_len > 32 ) 398 | goto more; 399 | 400 | } else { 401 | if (s->data->d_buf) { 402 | /* if we have a src pointer then copy */ 403 | memcpy ( dst_ptr, src_ptr, dst_len ); 404 | } else { 405 | /* otherwise we clear -- probably a .bss section */ 406 | memset ( dst_ptr, 0, dst_len ); 407 | } 408 | /* prep for next call */ 409 | s->scn_offset += dst_len; 410 | } 411 | 412 | bail: 413 | ES_PRINT(DEBUG,"read_elf_cb: returns %d\n", 414 | eof); 415 | return eof; 416 | } 417 | 418 | 419 | /* open_elf_file does just that opens s->fd as s->elf for read/write access */ 420 | static int 421 | open_elf_file( sign_session_t *s ) 422 | { 423 | int err; 424 | 425 | ES_PRINT(DEBUG,"%s: opening file as elf\n", __PRETTY_FUNCTION__); 426 | 427 | s->elf = elf_begin( s->fd, ELF_C_RDWR, NULL ); 428 | switch( elf_kind(s->elf) ) { 429 | case ELF_K_ELF: 430 | ES_PRINT(DEBUG, "%s: ELF file format detected\n", s->file); 431 | 432 | s->phdr = NULL; 433 | err = 1; 434 | 435 | /* get Elf and Program Headers */ 436 | if( !(s->ehdr = elf32_getehdr(s->elf)) ) { 437 | ES_PRINT(ERROR, "%s: %s\n", s->file, elf_errmsg(-1)); 438 | 439 | } else if ( s->ehdr->e_phnum 440 | && !(s->phdr = elf32_getphdr(s->elf)) ) { 441 | ES_PRINT(ERROR, "%s: %s\n", s->file, elf_errmsg(-1)); 442 | 443 | } else { 444 | err = 0; 445 | } 446 | break; 447 | 448 | case ELF_K_AR: 449 | err = 1; 450 | ES_PRINT(ERROR, "%s: elf_kind of ELF_K_AR is not supported\n", 451 | s->file); 452 | break; 453 | 454 | default: 455 | err = 1; 456 | ES_PRINT(ERROR, "%s: file format not recognized", s->file); 457 | break; 458 | } 459 | 460 | return err; 461 | } 462 | 463 | 464 | /* prepare_elfgpg_sections makes sure that .pgptab and .pgpsig sections 465 | * exist in elf object -- if they do not then the object is updated 466 | * (not the file); the sign_session_t *s pgp{tab,sig}_{scn,tab} are also 467 | * updated appropriately; */ 468 | static int 469 | prepare_elfgpg_sections( sign_session_t *s ) 470 | { 471 | int err = 1; 472 | 473 | /* assume we don't need a second pass */ 474 | s->new_sections = 0; 475 | 476 | ES_PRINT(DEBUG, "%s: locating the .pgptab section\n", 477 | __PRETTY_FUNCTION__); 478 | 479 | if( (s->pgptab_scn = elf_findscn(s->elf, ".pgptab")) ) { 480 | ES_PRINT(DEBUG, " ^^ .pgptab section exists\n"); 481 | /* section exists, get the data */ 482 | if( !(s->pgptab_data = elf_getdata(s->pgptab_scn,NULL)) ) { 483 | ES_PRINT(ERROR, "%s: elf_getdata .pgptab: %s\n", 484 | s->file, elf_errmsg(-1)); 485 | goto bail; 486 | } 487 | 488 | } else { 489 | ES_PRINT(DEBUG, " ^^ .pgptab section will be created\n"); 490 | /* create a new table entry for .pgptab */ 491 | if( !(s->pgptab_scn = create_section( s->elf, SHT_PGPTAB, 492 | ".pgptab" )) ) { 493 | ES_PRINT(ERROR, "%s: create_section .pgptab: %s\n", 494 | s->file, 495 | elf_errmsg(-1)); 496 | goto bail; 497 | } 498 | 499 | /* create data for the section */ 500 | if( !(s->pgptab_data = elf_newdata(s->pgptab_scn)) ) { 501 | ES_PRINT(ERROR, "%s: elf_newdata .pgptab: %s\n", 502 | s->file, elf_errmsg(-1)); 503 | goto bail; 504 | } 505 | 506 | /* creating sections means we need a second pass */ 507 | s->new_sections++; 508 | } 509 | 510 | /* update the object to include this table */ 511 | s->pgptab_data->d_align = 1; 512 | s->pgptab_data->d_size = s->ehdr->e_shnum * sizeof(Elf32_Pgp); 513 | s->pgptab_data->d_type = ELF_T_BYTE; 514 | s->pgptab_data->d_buf = s->pgptab_head; 515 | 516 | ES_PRINT(DEBUG, "%s: elf_update .pgptab...\n", s->file); 517 | ES_PRINT(DEBUG, "%s: ->d_align = %"PRIuMAX"\n", s->file, 518 | s->pgptab_data->d_align); 519 | ES_PRINT(DEBUG, "%s: ->d_size = %"PRIuMAX"\n", s->file, 520 | s->pgptab_data->d_size); 521 | ES_PRINT(DEBUG, "%s: ->d_type = %d\n", s->file, 522 | s->pgptab_data->d_type); 523 | ES_PRINT(DEBUG, "%s: ->d_buf = %p\n", s->file, 524 | s->pgptab_data->d_buf); 525 | 526 | if( elf_update( s->elf, ELF_C_NULL ) == -1 ) { 527 | ES_PRINT(ERROR, "elf_update: %s\n", elf_errmsg(-1)); 528 | goto bail; 529 | } 530 | 531 | ES_PRINT(DEBUG, "%s: locating the .pgpsig section\n", 532 | __PRETTY_FUNCTION__); 533 | 534 | if( (s->pgpsig_scn = elf_findscn( s->elf, ".pgpsig" )) ) { 535 | ES_PRINT(DEBUG, " ^^ .pgpsig section exists\n"); 536 | /* section exists, get the data */ 537 | if( !(s->pgpsig_data = elf_getdata(s->pgpsig_scn,NULL)) ) { 538 | ES_PRINT(ERROR, "%s: elf_getdata .pgpsig: %s\n", 539 | s->file, elf_errmsg(-1)); 540 | goto bail; 541 | } 542 | 543 | } else { 544 | ES_PRINT(DEBUG, " ^^ .pgpsig section will be created\n"); 545 | /* create a new section entry for .pgpsig */ 546 | if( !(s->pgpsig_scn = create_section( s->elf, SHT_PGPSIG, 547 | ".pgpsig" )) ) { 548 | ES_PRINT(ERROR, "%s: create_section .pgpsig: %s\n", 549 | s->file, 550 | elf_errmsg(-1)); 551 | goto bail; 552 | } 553 | 554 | /* create data for the section */ 555 | if( !(s->pgpsig_data = elf_newdata(s->pgpsig_scn)) ) { 556 | ES_PRINT(ERROR, "%s: elf_newdata: %s\n", s->file, 557 | elf_errmsg(-1)); 558 | goto bail; 559 | } 560 | 561 | /* creating sections means we need a second pass */ 562 | s->new_sections++; 563 | } 564 | 565 | /* update the elf file to include this structure */ 566 | s->pgpsig_data->d_align = 1; 567 | s->pgpsig_data->d_size = 65; /* is this large enough for any sig? */ 568 | s->pgpsig_data->d_type = ELF_T_BYTE; 569 | s->pgpsig_data->d_buf = s->sig; 570 | 571 | ES_PRINT(DEBUG, "%s: elf_update .pgpsig...\n", s->file); 572 | ES_PRINT(DEBUG, "%s: ->d_align = %"PRIuMAX"\n", s->file, 573 | s->pgptab_data->d_align); 574 | ES_PRINT(DEBUG, "%s: ->d_size = %"PRIuMAX"\n", s->file, 575 | s->pgptab_data->d_size); 576 | ES_PRINT(DEBUG, "%s: ->d_type = %d\n", s->file, 577 | s->pgptab_data->d_type); 578 | ES_PRINT(DEBUG, "%s: ->d_buf = %p\n", s->file, 579 | s->pgptab_data->d_buf); 580 | 581 | if( elf_update( s->elf, ELF_C_NULL ) == -1 ) { 582 | ES_PRINT(ERROR, "%s: elf_update: %s\n", s->file, 583 | elf_errmsg(-1)); 584 | err = -1; 585 | goto bail; 586 | } 587 | 588 | /* no error */ 589 | err = 0; 590 | bail: 591 | return err; 592 | } 593 | 594 | 595 | /* generate_pgptab 596 | * expects that the pgptab section was already created; this fn fills the 597 | * contents of the section data and updates the elf object (not disk file) */ 598 | static int 599 | generate_pgptab( sign_session_t *s ) 600 | { 601 | int err = -1; 602 | Elf32_Pgp pgp; 603 | 604 | ES_PRINT(INFO,"%s: generating .pgptab entires...\n", s->file); 605 | ES_PRINT(INFO," %-7s %-13s %5s %s\n", 606 | "entry", "type", "size", "name"); 607 | 608 | /* first add the elf header */ 609 | pgp.pt_type = ELF_PT_EHDR; 610 | pgp.pt_size = sizeof(*(s->ehdr)); 611 | pgp.pt_shndx = -1; 612 | pgptab_add( s, &pgp ); 613 | 614 | ES_PRINT(INFO,"+ %-7s %-13s %5d %s\n", 615 | "EHDR", "", pgp.pt_size, ""); 616 | 617 | /* second add the program header */ 618 | pgp.pt_type = ELF_PT_PHDR; 619 | pgp.pt_size = sizeof(*(s->phdr)); 620 | pgp.pt_shndx = -1; 621 | pgptab_add( s, &pgp ); 622 | 623 | ES_PRINT(INFO,"+ %-7s %-13s %5d %s\n", 624 | "PHDR", "", pgp.pt_size, ""); 625 | 626 | /* finally add all of the sections */ 627 | s->scn=NULL; 628 | while((s->shdr = elf32_getshdr(s->scn = elf_nextscn(s->elf,s->scn)))) { 629 | const char *tname, *sname; 630 | char type_number[16]; 631 | int ndx; 632 | 633 | /* this is the section index */ 634 | ndx = elf_ndxscn(s->scn); 635 | 636 | /* make sure we have a type for this section */ 637 | tname = elf_sht_string (s->shdr->sh_type); 638 | if (!tname) { 639 | tname = type_number; 640 | sprintf (type_number, "0x%08x", s->shdr->sh_type); 641 | } 642 | 643 | /* get the name of the elf section we are looking at */ 644 | sname = elf_strptr(s->elf, s->ehdr->e_shstrndx, 645 | s->shdr->sh_name); 646 | 647 | /* only look at interesting sections */ 648 | if( !sname || s->shdr->sh_type == SHT_NULL ) { 649 | //|| s->shdr->sh_type == SHT_NOBITS ) { 650 | ES_PRINT(INFO," SCN %-3d %-13s %5s %-10s -- " 651 | "skipping null section\n", ndx, 652 | tname, "", sname?sname:""); 653 | continue; 654 | } 655 | /* skip over the .pgptab and .pgpsig sections */ 656 | if( s->shdr->sh_type >= SHT_LOUSER 657 | && s->shdr->sh_type <= SHT_HIUSER ) { 658 | if( !strcmp( sname, ".pgptab" ) 659 | || !strcmp( sname, ".pgpsig" ) ) { 660 | ES_PRINT(INFO," SCN %-3d %-13s %5s %-10s" 661 | " -- skipping internal section\n", 662 | ndx, tname, "", sname); 663 | continue; 664 | } 665 | } 666 | /* get the data info structure */ 667 | if( !(s->data = elf_getdata(s->scn,NULL)) ) { 668 | ES_PRINT(INFO," SCN %-3d %-13s %5s %s\n", 669 | ndx, tname, "", sname); 670 | continue; 671 | } 672 | 673 | ES_PRINT(INFO,"+ SCN %-3d %-13s %5"PRIuMAX" %s\n", 674 | ndx, tname, s->data->d_size, sname); 675 | 676 | /* compose and append the pgptab entry */ 677 | pgp.pt_type = ELF_PT_SCN; 678 | pgp.pt_size = s->data->d_size; 679 | pgp.pt_shndx = elf_ndxscn(s->scn); 680 | pgptab_add( s, &pgp ); 681 | } 682 | 683 | /* update the object to include this table */ 684 | s->pgptab_data->d_align = 1; 685 | s->pgptab_data->d_size = s->pgptab_tail - s->pgptab_head; 686 | s->pgptab_data->d_type = ELF_T_BYTE; 687 | s->pgptab_data->d_buf = s->pgptab_head; 688 | 689 | if( elf_update( s->elf, ELF_C_NULL ) == -1 ) { 690 | ES_PRINT(ERROR, "elf_update: %s\n", elf_errmsg(-1)); 691 | goto bail; 692 | } 693 | 694 | /* success */ 695 | err = 0; 696 | bail: 697 | return err; 698 | } 699 | 700 | 701 | /* generate_pgptab 702 | * expects that the pgptab section was already created; this fn fills the 703 | * contents of the section data and updates the elf object (not disk file) */ 704 | static int 705 | generate_pgpsig( sign_session_t *s ) 706 | { 707 | int ret=-1; 708 | gpgme_error_t err; 709 | gpgme_data_t in, out; 710 | size_t oslen; 711 | 712 | /* start processing creating the .pgptab at elf header */ 713 | s->tab_index = 0; 714 | s->scn_offset = 0; 715 | 716 | ES_PRINT(INFO,"%s: generating .pgpsig section...\n", s->file); 717 | ES_PRINT(INFO," %-7s %-13s %5s %s\n", 718 | "entry", "type", "size", "name"); 719 | 720 | err = gpgme_data_new_from_cbs (&in, &elf_data, s); 721 | if( err ) { 722 | ES_PRINT(ERROR, "gpgme_data_new: %s\n", gpgme_strerror(err)); 723 | goto bail; 724 | } 725 | 726 | err = gpgme_data_new( &out ); 727 | if( err ) { 728 | ES_PRINT(ERROR, "gpgme_data_new: %s\n", gpgme_strerror(err)); 729 | goto bail; 730 | } 731 | 732 | err = gpgme_op_sign (s->gpgme_ctx, in, out, GPGME_SIG_MODE_DETACH); 733 | if( err ) { 734 | ES_PRINT(ERROR, "gpgme_op_sign: %s\n", gpgme_strerror(err)); 735 | goto bail; 736 | } 737 | 738 | oslen = s->slen = sizeof(s->sig); 739 | err = gpgme_data_read (out, s->sig, oslen); 740 | if( err ) { 741 | if( oslen==s->slen ) { 742 | ES_PRINT(ERROR, "sign_gpg: signature buffer was " 743 | "too short\n"); 744 | goto bail; 745 | } else if ( err!=GPG_ERR_EOF ) { 746 | ES_PRINT(ERROR, "gpgme_data_read: %s\n", 747 | gpgme_strerror(err)); 748 | goto bail; 749 | } 750 | } else { 751 | ES_PRINT(INFO, "%s: sig %"PRIuMAX" bytes\n", s->file, s->slen); 752 | } 753 | 754 | s->pgpsig_data->d_align = 1; 755 | s->pgpsig_data->d_size = s->slen; 756 | s->pgpsig_data->d_type = ELF_T_BYTE; 757 | s->pgpsig_data->d_buf = s->sig; 758 | 759 | if( elf_update( s->elf, ELF_C_NULL ) == -1 ) { 760 | ES_PRINT(ERROR, "elf_update: %s\n", elf_errmsg(-1)); 761 | err = -1; 762 | goto bail; 763 | } 764 | 765 | ret=0; 766 | bail: 767 | gpgme_data_release(in); 768 | gpgme_data_release(out); 769 | return ret; 770 | } 771 | 772 | 773 | /* commit all changes made to the elf objects to the file that was opened 774 | * earlier */ 775 | static int 776 | commit_elf_to_file( sign_session_t *s ) 777 | { 778 | int err = 0; 779 | 780 | ES_PRINT(DEBUG, "%s: writing changes to disk\n", __PRETTY_FUNCTION__); 781 | if( elf_update( s->elf, ELF_C_WRITE ) == -1 ) { 782 | ES_PRINT(ERROR, "elf_update: %s\n", elf_errmsg(-1)); 783 | err = -1; 784 | } 785 | 786 | return err; 787 | } 788 | 789 | 790 | /* entry point to the module */ 791 | int 792 | do_elfsign( const char *file, int fd ) 793 | { 794 | int ret; 795 | int loop = 0; 796 | sign_session_t session; 797 | gpgme_ctx_t gpgme_ctx; 798 | 799 | ES_PRINT(DEBUG,"elfsign( '%s', %d )...\n" 800 | "\tverbose = %d\n" 801 | "\tforce = %d\n" 802 | "\tkeyname = %s\n" 803 | "\tkeyring = %s\n" 804 | "\talgname = %s\n", 805 | file, fd, 806 | opts->verbose, opts->force, opts->keyname, 807 | opts->keyring, opts->algname ); 808 | 809 | memset(&session, 0, sizeof(sign_session_t)); 810 | session.file = file; 811 | session.fd = fd; 812 | 813 | ret = configure_gpg( &gpgme_ctx ); 814 | if (ret) { 815 | ES_PRINT (ERROR, "%s: failed to init libgpgme\n", file); 816 | goto bail; 817 | } 818 | 819 | /* store the gpgme contxt in the session */ 820 | session.gpgme_ctx = gpgme_ctx; 821 | 822 | again: 823 | ret = open_elf_file( &session ); 824 | if (ret) { 825 | ES_PRINT (ERROR, "%s: failed to open file\n", file); 826 | goto bail; 827 | } 828 | 829 | ret = prepare_elfgpg_sections( &session ); 830 | if (ret) { 831 | ES_PRINT (ERROR, "%s: failed to prepare sections\n", file); 832 | goto bail; 833 | } 834 | 835 | ret = generate_pgptab( &session ); 836 | if (ret) { 837 | ES_PRINT (ERROR, "%s: failed to generate .pgptab\n", file); 838 | goto bail; 839 | } 840 | 841 | ret = generate_pgpsig( &session ); 842 | if (ret) { 843 | ES_PRINT (ERROR, "%s: failed to generate .pgpsig\n", file); 844 | goto bail; 845 | } 846 | 847 | if( !ret && session.new_sections ) { 848 | 849 | ret = commit_elf_to_file( &session ); 850 | if( ret ) { 851 | ES_PRINT (ERROR, "%s: failed to commit new sections\n", 852 | file); 853 | goto bail; 854 | } 855 | 856 | /* finalize the elf file */ 857 | elf_end(session.elf); 858 | 859 | /* reset the structure and put back the values we need */ 860 | memset(&session, 0, sizeof(sign_session_t)); 861 | session.file = file; 862 | session.fd = fd; 863 | session.gpgme_ctx = gpgme_ctx; 864 | 865 | if (++loop < 2) { 866 | ES_PRINT(INFO, "%s: created pgp sections; " 867 | "string pass %d\n", file, loop); 868 | 869 | goto again; 870 | } 871 | 872 | ES_PRINT(ERROR, "%s: internal error; endless loop detected\n", 873 | file); 874 | ret = -EFAULT; 875 | } 876 | 877 | ret = commit_elf_to_file( &session ); 878 | if( ret ) { 879 | ES_PRINT (ERROR, "%s: failed to commit elf file\n", file); 880 | goto bail; 881 | } 882 | 883 | /* success */ 884 | ES_PRINT(NORM, "%s: signed\n", file); 885 | 886 | bail: 887 | elf_end(session.elf); 888 | gpgme_release( gpgme_ctx ); 889 | 890 | if( session.pgptab_head ) 891 | free( session.pgptab_head ); 892 | 893 | return ret; 894 | } 895 | -------------------------------------------------------------------------------- /src/sign.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_SIGN_H 24 | #define ELFSIGN_SIGN_H 25 | 26 | int do_elfsign( const char *name, int fd ); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/verify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "ep_session.h" 32 | 33 | #include "options.h" 34 | #include "verify.h" 35 | #include "elfgpg.h" 36 | #include "elfhelp.h" 37 | #include "elfstrings.h" 38 | 39 | typedef struct verify_session_s 40 | { 41 | elfgpg_session_t *elfgpg_session; 42 | 43 | /* context for gpgme */ 44 | gpgme_ctx_t gpgme_ctx; 45 | 46 | /* how far are we in the read */ 47 | u_int32_t tab_index; 48 | u_int32_t scn_offset; 49 | int read_cb_eof; 50 | 51 | /* entry in the .pgptab */ 52 | Elf32_Pgp pgp; 53 | 54 | /* section currently being processed by the read callback */ 55 | Elf32_Shdr *shdr; 56 | Elf_Data *data; 57 | Elf_Scn *scn; 58 | 59 | /* fake data for data pointer */ 60 | Elf_Data fake_data; 61 | } 62 | verify_session_t; 63 | 64 | 65 | static int 66 | configure_gpg( gpgme_ctx_t *ctx ) 67 | { 68 | gpgme_error_t err; 69 | 70 | err = gpgme_new(ctx); 71 | if( err ) { 72 | ES_PRINT(ERROR, "gpgme_new: %s\n", gpgme_strerror(err)); 73 | return -1; 74 | } 75 | 76 | gpgme_set_textmode(*ctx,1); 77 | gpgme_set_armor(*ctx,0); 78 | 79 | return 0; 80 | } 81 | 82 | 83 | static void 84 | print_short_sig_stat ( verify_session_t *s, gpgme_verify_result_t result, 85 | gpgme_error_t verify_error) 86 | { 87 | const char *id=NULL, *alg=NULL, *name=NULL, 88 | *email=NULL, *note=NULL; 89 | gpgme_key_t key; 90 | int rc; 91 | 92 | key = gpgme_signers_enum(s->gpgme_ctx, 0); 93 | if (key) { 94 | id = key->chain_id; 95 | if (key->subkeys) 96 | alg = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo); 97 | if (key->uids) { 98 | name = key->uids->name; 99 | email = key->uids->email; 100 | note = key->uids->comment; 101 | } 102 | } 103 | 104 | rc = ES_PRINT(INFO,"%-*s %-8s %s %s (%s) <%s>\n", 105 | opts->file_name_max, s->elfgpg_session->file, 106 | gpg_strerror(verify_error), 107 | id, name, note, email); 108 | 109 | /* will show a less verbose output */ 110 | if( !(rc) ) { 111 | const char *fmt, *val; 112 | if( email ) { 113 | fmt = "%-*s %-8s <%s>\n"; 114 | val = email; 115 | } else { 116 | fmt = "%-*s %-8s %s\n"; 117 | val = id; 118 | } 119 | ES_PRINT(NORM, fmt, 120 | opts->file_name_max, s->elfgpg_session->file, 121 | gpg_strerror(verify_error), 122 | val); 123 | } 124 | } 125 | 126 | 127 | static void 128 | print_verbose_sig_stat (verify_session_t *s, gpgme_verify_result_t result, 129 | gpgme_error_t verify_error) 130 | { 131 | int idx; 132 | gpgme_key_t key; 133 | 134 | ES_PRINT(DEBUG, "print_verbose_sig_stat: dumping status...\n"); 135 | 136 | for(idx=0; (key = gpgme_signers_enum(s->gpgme_ctx, idx)); idx++) { 137 | ES_PRINT(INFO, "sig %d: status: %s\n", 138 | idx, 139 | gpg_strerror(verify_error)); 140 | ES_PRINT(INFO, "sig %d: fpr/keyid=`%s' %s <%s>\n", 141 | idx, key->chain_id, 142 | key->uids->name, 143 | key->uids->email); 144 | } 145 | } 146 | 147 | 148 | static ssize_t elf_data_read (void* opaque, void *buff, size_t blen); 149 | static struct gpgme_data_cbs elf_data = { 150 | .read = elf_data_read, 151 | .write = NULL, 152 | .seek = NULL, 153 | .release = NULL, 154 | }; 155 | 156 | static ssize_t 157 | elf_data_read (void* opaque, void *buff, size_t blen) 158 | { 159 | verify_session_t *s = (void*)opaque; 160 | elfgpg_session_t *es = s->elfgpg_session; 161 | int eof; /* 1 if there is no more data to read */ 162 | void *src_ptr, *dst_ptr; 163 | size_t src_len, dst_len; 164 | const char *tname, *sname; 165 | char type_number[16]; 166 | int ndx; 167 | 168 | ES_PRINT(DEBUG, "%s(%p, %p, %"PRIuMAX"\n", 169 | __PRETTY_FUNCTION__, opaque, buff, blen); 170 | 171 | dst_ptr = buff; 172 | dst_len = blen; 173 | 174 | if( (eof = s->read_cb_eof) ) 175 | goto bail; 176 | 177 | more: 178 | if( !s->scn_offset ) { 179 | /* means that we need to fetch the next pgp 180 | * entry from .pgptab */ 181 | long pgp_offset = s->tab_index * sizeof(Elf32_Pgp); 182 | 183 | ES_PRINT(DEBUG, "read_elf_cb: !offset: new section %d\n", 184 | s->tab_index); 185 | 186 | if( (pgp_offset+sizeof(Elf32_Pgp)) > es->pgptab_data->d_size ) { 187 | ES_PRINT(DEBUG,"%s: got to the end of .pgptab\n", 188 | es->file); 189 | s->read_cb_eof = 1; 190 | goto bail; 191 | 192 | } 193 | memcpy( &s->pgp, es->pgptab_data->d_buf + pgp_offset, 194 | sizeof(Elf32_Pgp) ); 195 | 196 | ES_PRINT(DEBUG, "read_elf_cb: pgptab[%d] = { %d, %d, %d }\n", 197 | s->tab_index, s->pgp.pt_type, s->pgp.pt_size, 198 | s->pgp.pt_shndx); 199 | 200 | switch( s->pgp.pt_type ) { 201 | case ELF_PT_EHDR: 202 | /* we got an elf header */ 203 | s->data = &s->fake_data; 204 | s->data->d_buf = (void*)es->ehdr; 205 | s->data->d_size = s->pgp.pt_size; 206 | 207 | ES_PRINT(INFO," %-7s %-13s %5d %s\n", 208 | "EHDR", "", s->pgp.pt_size, ""); 209 | break; 210 | 211 | case ELF_PT_PHDR: 212 | /* get got a program header */ 213 | s->data = &s->fake_data; 214 | s->data->d_buf = (void*)es->phdr; 215 | s->data->d_size = s->pgp.pt_size; 216 | 217 | ES_PRINT(INFO," %-7s %-13s %5d %s\n", 218 | "PHDR", "", s->pgp.pt_size, ""); 219 | break; 220 | 221 | case ELF_PT_SCN: 222 | /* this is the section index */ 223 | ndx = s->pgp.pt_shndx; 224 | 225 | /* we know the section number, get the section & header */ 226 | s->scn = elf_getscn(es->elf, ndx); 227 | if( !(s->shdr = elf32_getshdr(s->scn)) ) { 228 | ES_PRINT(ERROR,"%s: shndx=%d: %s\n", es->file, 229 | ndx, elf_errmsg(-1)); 230 | eof = s->read_cb_eof = 1; 231 | goto bail; 232 | } 233 | 234 | /* make sure we have a type for this section */ 235 | tname = elf_sht_string (s->shdr->sh_type); 236 | if (!tname) { 237 | tname = type_number; 238 | sprintf (type_number, "0x%08x", 239 | s->shdr->sh_type); 240 | } 241 | 242 | /* get the name of the elf section we are looking at */ 243 | sname = elf_strptr(es->elf, es->ehdr->e_shstrndx, 244 | s->shdr->sh_name); 245 | 246 | /* now get the data for that section */ 247 | if( !(s->data = elf_getdata(s->scn, NULL)) ) { 248 | ES_PRINT(ERROR,"%s: get data %s\n", es->file, 249 | elf_errmsg(-1)); 250 | eof = s->read_cb_eof = 1; 251 | goto bail; 252 | } 253 | 254 | ES_PRINT(INFO," SCN %-3d %-13s %5"PRIuMAX" %s\n", 255 | ndx, tname, s->data->d_size, sname); 256 | break; 257 | 258 | default: 259 | ES_PRINT(ERROR,"%s: invalid .pgptab entry type " 260 | "at index %d\n", 261 | es->file, s->pgp.pt_shndx); 262 | eof = s->read_cb_eof = 1; 263 | goto bail; 264 | } 265 | } 266 | 267 | src_ptr = s->data->d_buf + s->scn_offset; 268 | src_len = s->data->d_size - s->scn_offset; 269 | if( !src_len ) 270 | goto bail; 271 | 272 | ES_PRINT(DEBUG,"read_elf_cb: have data @ %p of len %"PRIuMAX" bytes\n", 273 | src_ptr, src_len); 274 | 275 | /* test to see if all the current data block can be submitted */ 276 | if( src_len <= dst_len ) { 277 | if (s->data->d_buf) { 278 | /* if we have a src pointer then copy */ 279 | memcpy ( dst_ptr, src_ptr, src_len ); 280 | } else { 281 | /* otherwise we clear -- probably a .bss section */ 282 | memset ( dst_ptr, 0, src_len ); 283 | } 284 | /* move buffer pointer/size to after new addition */ 285 | dst_ptr += src_len; 286 | dst_len -= src_len; 287 | /* prep for next call */ 288 | s->scn_offset = 0; 289 | s->tab_index ++; 290 | 291 | if( !s->read_cb_eof && dst_len > 32 ) 292 | goto more; 293 | 294 | } else { 295 | if (s->data->d_buf) { 296 | /* if we have a src pointer then copy */ 297 | memcpy ( dst_ptr, src_ptr, dst_len ); 298 | } else { 299 | /* otherwise we clear -- probably a .bss section */ 300 | memset ( dst_ptr, 0, dst_len ); 301 | } 302 | /* prep for next call */ 303 | s->scn_offset += dst_len; 304 | } 305 | 306 | bail: 307 | ES_PRINT(DEBUG,"read_elf_cb: returns %d\n", eof); 308 | return eof; 309 | } 310 | 311 | 312 | static int 313 | init_process_elf( verify_session_t *s ) 314 | { 315 | int err; 316 | elfgpg_session_t *es = s->elfgpg_session; 317 | 318 | es->elf = elf_begin( es->fd, ELF_C_READ, NULL ); 319 | switch( elf_kind(es->elf) ) { 320 | case ELF_K_ELF: 321 | ES_PRINT(DEBUG, "%s: ELF file format detected\n", es->file); 322 | 323 | es->phdr = NULL; 324 | err = 1; 325 | 326 | /* get Elf Program Headers then the scn/shdr/data for the tab/sig scns */ 327 | if( !(es->ehdr = elf32_getehdr(es->elf)) ) { 328 | ES_PRINT(ERROR, "%s: %s\n", es->file, elf_errmsg(-1)); 329 | 330 | } else if ( es->ehdr->e_phnum 331 | && !(es->phdr = elf32_getphdr(es->elf)) ) { 332 | ES_PRINT(ERROR, "%s: %s\n", es->file, elf_errmsg(-1)); 333 | 334 | } else if ( !(es->pgptab_hdr = elf32_getshdr( es->pgptab_scn 335 | = elf_findscn(es->elf, ".pgptab"))) ) { 336 | if ( elf_errno() ) { 337 | ES_PRINT(ERROR, "%s: find .pgptab: %s\n", 338 | es->file, elf_errmsg(-1)); 339 | } else { 340 | ES_PRINT(NORM, "%-*s %-8s\n", 341 | opts->file_name_max, es->file, 342 | gpgme_strerror( 343 | GPGME_SIG_STAT_NOSIG)); 344 | } 345 | 346 | } else if ( !(es->pgptab_data = elf_getdata(es->pgptab_scn, 347 | NULL)) ) { 348 | ES_PRINT(ERROR, "%s: data .pgptab: %s\n", es->file, 349 | elf_errmsg(-1)); 350 | 351 | } else if ( !(es->pgpsig_hdr = elf32_getshdr( es->pgpsig_scn 352 | = elf_findscn(es->elf, ".pgpsig"))) ) { 353 | if ( elf_errno() ) { 354 | ES_PRINT(ERROR, "%s: find .pgpsig: %s\n", 355 | es->file, elf_errmsg(-1)); 356 | } else { 357 | ES_PRINT(NORM, "%-*s %-8s\n", 358 | opts->file_name_max, es->file, 359 | gpgme_strerror( 360 | GPGME_SIG_STAT_NOSIG)); 361 | } 362 | 363 | } else if ( !(es->pgpsig_data = elf_getdata(es->pgpsig_scn, 364 | NULL)) ) { 365 | ES_PRINT(ERROR, "%s: data .pgpsig: %s\n", es->file, 366 | elf_errmsg(-1)); 367 | 368 | } else { 369 | err = 0; 370 | } 371 | break; 372 | 373 | case ELF_K_AR: 374 | err = 1; 375 | ES_PRINT(ERROR, "%s: elf_kind of ELF_K_AR is not supported\n", 376 | es->file); 377 | break; 378 | 379 | default: 380 | err = 1; 381 | ES_PRINT(ERROR, "%s: file format not recognized", es->file); 382 | break; 383 | } 384 | 385 | return err; 386 | } 387 | 388 | 389 | static int 390 | process_elf( verify_session_t *s ) 391 | { 392 | int ret=-1; 393 | gpgme_error_t err; 394 | gpgme_data_t sig, data; 395 | gpgme_verify_result_t result; 396 | elfgpg_session_t *es = s->elfgpg_session; 397 | 398 | /* start processing the .pgptab at the first entry */ 399 | s->tab_index = 0; 400 | s->scn_offset = 0; 401 | 402 | ES_PRINT(INFO,"%s: validating .pgptab entires...\n", es->file); 403 | ES_PRINT(INFO," %-7s %-13s %5s %s\n", 404 | "entry", "type", "size", "name"); 405 | 406 | err = gpgme_data_new_from_cbs (&data, &elf_data, s); 407 | if( err ) { 408 | ES_PRINT(ERROR, "gpgme_data_new_with_read_cb: %s\n", 409 | gpgme_strerror(err)); 410 | goto bail; 411 | } 412 | 413 | ES_PRINT(DEBUG, "process_elf: creating sig gpgme data object\n"); 414 | 415 | ES_PRINT(DEBUG, "process_elf: sig is of size %"PRIuMAX"\n", 416 | es->pgpsig_data->d_size); 417 | err = gpgme_data_new_from_mem( &sig, es->pgpsig_data->d_buf, 418 | es->pgpsig_data->d_size, 0 ); 419 | if( err ) { 420 | ES_PRINT(ERROR, "gpgme_data_new_from_mem: %s\n", 421 | gpgme_strerror(err)); 422 | goto bail; 423 | } 424 | 425 | ES_PRINT(DEBUG, "process_elf: calling gpgme_op_verify\n"); 426 | 427 | err = gpgme_op_verify (s->gpgme_ctx, sig, NULL, data); 428 | if( err ) { 429 | ES_PRINT(ERROR, "gpgme_op_verify: %s\n", 430 | gpgme_strerror(err)); 431 | goto bail; 432 | } 433 | 434 | result = gpgme_op_verify_result (s->gpgme_ctx); 435 | 436 | print_short_sig_stat( s, result, err ); 437 | if( ES_SHOW(DEBUG) ) 438 | print_verbose_sig_stat( s, result, err ); 439 | 440 | ret=0; 441 | bail: 442 | #if defined(AVOID_GPGME_CALLBACK) 443 | if( big_buffer_ptr ) 444 | free(big_buffer_ptr); 445 | #endif 446 | 447 | gpgme_data_release(sig); 448 | gpgme_data_release(data); 449 | 450 | return ret; 451 | } 452 | 453 | 454 | int 455 | do_elfverify( const char *file, int fd ) 456 | { 457 | int ret; 458 | elfgpg_session_t elfgpg_session; 459 | verify_session_t session; 460 | 461 | ES_PRINT(DEBUG,"elfverify( '%s', %d )...\n" 462 | "\tverbose = %d\n" 463 | "\tforce = %d\n" 464 | "\tkeyname = %s\n" 465 | "\tkeyring = %s\n" 466 | "\talgname = %s\n", 467 | file, fd, 468 | opts->verbose, opts->force, opts->keyname, 469 | opts->keyring, opts->algname ); 470 | 471 | memset(&elfgpg_session, 0, sizeof(elfgpg_session_t)); 472 | elfgpg_session.file = file; 473 | elfgpg_session.fd = fd; 474 | 475 | memset(&session, 0, sizeof(verify_session_t)); 476 | session.elfgpg_session = &elfgpg_session; 477 | 478 | ret = configure_gpg( &session.gpgme_ctx ); 479 | 480 | if( ! ret ) 481 | ret = init_process_elf( &session ); 482 | 483 | if( ! ret ) 484 | ret = process_elf( &session ); 485 | 486 | elf_end(elfgpg_session.elf); 487 | gpgme_release( session.gpgme_ctx ); 488 | 489 | return ret; 490 | } 491 | -------------------------------------------------------------------------------- /src/verify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001-2003 Bart Trojanowski 3 | * 4 | * This file is a part of the elfsign utility 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ident "%Z%%M% %I% %E% Bart Trojanowski " 22 | 23 | #ifndef ELFSIGN_VERIFY_H 24 | #define ELFSIGN_VERIFY_H 25 | 26 | int do_elfverify( const char *name, int fd ); 27 | 28 | #endif 29 | --------------------------------------------------------------------------------