From: Gui Chen Date: Wed, 23 Jul 2014 10:54:33 +0000 (-0400) Subject: Imported Upstream version 1.0.7 X-Git-Tag: submit/devel/20190730.074546~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=12579d8c8ca610fc11dda32b88130a60da580d93;p=tools%2Fisomd5sum.git Imported Upstream version 1.0.7 --- 12579d8c8ca610fc11dda32b88130a60da580d93 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb89a59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +checkisomd5 +implantisomd5 +*.o +*.so +*~ +*.a +*.tar.bz2 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2ed24a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,71 @@ +PYVER := $(shell python -c 'import sys; print sys.version[0:3]') +PYTHON = python$(PYVER) +PYTHONINCLUDE = /usr/include/$(PYTHON) + +VERSION=1.0.7 + +ifneq (,$(filter sparc64 ppc64 x86_64 s390x,$(shell uname -m))) +LIBDIR = lib64 +else +LIBDIR = lib +endif + +CFLAGS = $(RPM_OPT_FLAGS) -Wall -Werror -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 -fPIC -I$(PYTHONINCLUDE) + +OBJECTS = md5.o libimplantisomd5.o checkisomd5.o implantisomd5 +SOURCES = $(patsubst %.o,%.c,$(OBJECTS)) +LDFLAGS += -fPIC + +PYOBJS = pyisomd5sum.o libcheckisomd5.a libimplantisomd5.a + +all: implantisomd5 checkisomd5 pyisomd5sum.so libimplantisomd5.a libcheckisomd5.a + +%.o: %.c + $(CC) -c -O $(CFLAGS) -o $@ $< + +implantisomd5: implantisomd5.o libimplantisomd5.a + $(CC) -lpopt $(CFLAGS) implantisomd5.o libimplantisomd5.a -o implantisomd5 + +checkisomd5: checkisomd5.o libcheckisomd5.a + $(CC) -lpopt $(CFLAGS) checkisomd5.o libcheckisomd5.a -o checkisomd5 + +libimplantisomd5.a: libimplantisomd5.a(libimplantisomd5.o md5.o) + +libcheckisomd5.a: libcheckisomd5.a(libcheckisomd5.o md5.o) + +pyisomd5sum.so: $(PYOBJS) + $(CC) -shared -g -o pyisomd5sum.so -fpic $(PYOBJS) $(LDFLAGS) + +install: all install-bin install-python install-devel + +install-bin: + install -d -m 0755 $(DESTDIR)/usr/bin + install -d -m 0755 $(DESTDIR)/usr/share/man/man1 + install -m 0755 implantisomd5 $(DESTDIR)/usr/bin + install -m 0755 checkisomd5 $(DESTDIR)/usr/bin + install -m 0644 implantisomd5.1 $(DESTDIR)/usr/share/man/man1 + install -m 0644 checkisomd5.1 $(DESTDIR)/usr/share/man/man1 + +install-python: + install -d -m 0755 $(DESTDIR)/usr/$(LIBDIR)/$(PYTHON)/site-packages + install -m 0755 pyisomd5sum.so $(DESTDIR)/usr/$(LIBDIR)/$(PYTHON)/site-packages + +install-devel: + install -d -m 0755 $(DESTDIR)/usr/include + install -d -m 0755 $(DESTDIR)/usr/$(LIBDIR) + install -m 0644 libimplantisomd5.h $(DESTDIR)/usr/include/ + install -m 0644 libcheckisomd5.h $(DESTDIR)/usr/include/ + install -m 0644 libimplantisomd5.a $(DESTDIR)/usr/$(LIBDIR) + install -m 0644 libcheckisomd5.a $(DESTDIR)/usr/$(LIBDIR) + +clean: + rm -f *.o *.so *.pyc *.a .depend *~ + rm -f implantisomd5 checkisomd5 + +tag: + @git tag -a -m "Tag as $(VERSION)" -f $(VERSION) + @echo "Tagged as $(VERSION)" + +archive: + @git archive --format=tar --prefix=isomd5sum-$(VERSION)/ HEAD |bzip2 > isomd5sum-$(VERSION).tar.bz2 + @echo "The final archive is in isomd5sum-$(VERSION).tar.bz2" diff --git a/README b/README new file mode 100644 index 0000000..e848cd4 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +isomd5sum provides a way of making use of the ISO9660 application data +area to store md5sum data about the iso. This allows you to check the +iso given nothing more than the iso itself. + +isomd5sum is hosted as a fedorahosted project. The source can be +grabbed via git with + git clone git://git.fedorahosted.org/isomd5sum.git +or browsed via gitweb at + http://git.fedorahosted.org/git/?p=isomd5sum.git;a=summary + +Releases of isomd5sum are located at + http://fedorahosted.org/releases/i/s/isomd5sum + +You can send questions, enhancements, etc to anaconda-devel-list@redhat.com. diff --git a/checkisomd5.1 b/checkisomd5.1 new file mode 100644 index 0000000..78a3fa1 --- /dev/null +++ b/checkisomd5.1 @@ -0,0 +1,25 @@ +.TH "CHECKISOMD5" "1" +.SH "NAME" +checkisomd5 \(em check an MD5 checksum implanted by \fBimplantisomd5\fR +.SH "SYNOPSIS" +.PP +\fBcheckisomd5\fR [\fB\-\-md5sumonly\fP] [\fB\-\-verbose\fP] [\fB\-\-gauge\fP] [isofilename | blockdevice ] +.SH "DESCRIPTION" +.PP +This manual page documents briefly the \fBcheckisomd5\fR command. \fBcheckisomd5\fR is a program that checks an embedded MD5 checksum in a ISO9660 image (.iso), or block device. The checksum is embedded by the corresponding \fBimplantisomd5\fR command. +.PP +The check can be aborted by pressing Esc key. +.SH "EXIT STATUS" +.PP +Program returns exit status 0 if the checksum is correct, or 1 if the checksum is incorrect, non-existent, or check was aborted. +.SH "OPTIONS" +.IP "\fB\-\-md5sumonly\fP" 10 +Do not check the target. Instead, output human-readable information about the target's checksums. +.IP "\fB\-\-verbose\fP" 10 +Display human-readable progress as the target is checked. Without this option, nothing is outputted except errors. +.IP "\fB\-\-gauge\fP" 10 +Display a series of numbers from 0 to 100, corresponding to check progress. This output can be piped to \fBdialog \-\-gauge\fR for a user-friendly progress bar. +.SH "SEE ALSO" +.PP +implantisomd5 (1). +.\" created by instant / docbook-to-man, Thu 07 Feb 2008, 13:43 diff --git a/checkisomd5.c b/checkisomd5.c new file mode 100644 index 0000000..df06f5f --- /dev/null +++ b/checkisomd5.c @@ -0,0 +1,178 @@ +/* + * checkosmd5 - simple program to check implanted md5sum + * Copyright (C) 2001-2007 Red Hat, Inc. + * Michael Fulbright + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "md5.h" +#include "libcheckisomd5.h" + +struct progressCBData { + int verbose; + int gauge; + int gaugeat; +}; + +int user_bailing_out() { + int retval = 0; + struct timeval timev; + fd_set rfds; + char ch; + + FD_ZERO(&rfds); + FD_SET(0,&rfds); + + timev.tv_sec = 0; + timev.tv_usec = 0; + + if (select(1, &rfds, NULL, NULL, &timev)) + if ((ch = getchar()) == 27) + retval = 1; + + return retval; +} + +static int outputCB(void *co, long long offset, long long total) { + struct progressCBData *data = co; + int gaugeval = -1; + + if (data->verbose) { + printf("\rChecking: %05.1f%%", (100.0*offset)/(total)); + fflush(stdout); + } + if (data->gauge) { + gaugeval = (100.0*offset)/(total); + if (gaugeval != data->gaugeat) { + printf("%d\n", gaugeval); + fflush(stdout); + data->gaugeat = gaugeval; + } + } + + return user_bailing_out(); +} + +static void usage(void) { + fprintf(stderr, "Usage: checkisomd5 [--md5sumonly] [--verbose] [--gauge] |\n\n"); + exit(1); +} + + +/* Process the result code and return the proper exit status value + */ +int processExitStatus(int rc) { + char * result; + + switch (rc) { + case ISOMD5SUM_CHECK_FAILED: + result = "FAIL.\n\nIt is not recommended to use this media."; + break; + case ISOMD5SUM_CHECK_ABORTED: + result = "UNKNOWN.\n\nThe media check was aborted."; + break; + case ISOMD5SUM_CHECK_NOT_FOUND: + result = "NA.\n\nNo checksum information available, unable to verify media."; + break; + case ISOMD5SUM_FILE_NOT_FOUND: + result = "NA.\n\nFile not found."; + break; + case ISOMD5SUM_CHECK_PASSED: + result = "PASS.\n\nIt is OK to use this media."; + break; + default: + result = "checkisomd5 ERROR - bad return value"; + break; + } + + fprintf(stderr, "\nThe media check is complete, the result is: %s\n", result); + + return(rc != ISOMD5SUM_CHECK_PASSED); +} + + +int main(int argc, char **argv) { + int rc; + const char **args; + int md5only; + int help; + struct progressCBData data; + poptContext optCon; + + memset(&data, 0, sizeof(struct progressCBData)); + + md5only = 0; + help = 0; + data.verbose = 0; + data.gauge = 0; + + struct poptOption options[] = { + { "md5sumonly", 'o', POPT_ARG_NONE, &md5only, 0 }, + { "verbose", 'v', POPT_ARG_NONE, &data.verbose, 0 }, + { "gauge", 'g', POPT_ARG_NONE, &data.gauge, 0}, + { "help", 'h', POPT_ARG_NONE, &help, 0}, + { 0, 0, 0, 0, 0} + }; + + static struct termios oldt, newt; + + optCon = poptGetContext("checkisomd5", argc, (const char **)argv, options, 0); + + if ((rc = poptGetNextOpt(optCon)) < -1) { + fprintf(stderr, "bad option %s: %s\n", + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + poptStrerror(rc)); + exit(1); + } + + if (help) + usage(); + + args = poptGetArgs(optCon); + if (!args || !args[0] || !args[0][0]) + usage(); + + if (md5only|data.verbose) { + rc = printMD5SUM((char *)args[0]); + if (rc < 0) { + exit(processExitStatus(rc)); + } + } + + if (md5only) + exit(0); + + printf("Press [Esc] to abort check.\n"); + + tcgetattr(0, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG | IEXTEN); + tcsetattr(0, TCSANOW, &newt); + rc = mediaCheckFile((char *)args[0], outputCB, &data); + tcsetattr(0, TCSANOW, &oldt); + + if (data.verbose) + printf("\n"); + + exit(processExitStatus(rc)); +} + diff --git a/implantisomd5.1 b/implantisomd5.1 new file mode 100644 index 0000000..e6219f1 --- /dev/null +++ b/implantisomd5.1 @@ -0,0 +1,18 @@ +.TH "IMPLANTISOMD5" "1" +.SH "NAME" +implantisomd5 \(em implant an MD5 checksum in an ISO9660 image +.SH "SYNOPSIS" +.PP +\fBimplantisomd5\fR [\fB\-\-force\fP] [\fB\-\-supported-iso\fP] [isofilename] +.SH "DESCRIPTION" +.PP +This manual page documents briefly the \fBimplantisomd5\fR command. \fBimplantisomd5\fR is a program that embeds an MD5 checksum in an unused section of and ISO9660 (.iso) image. This checksum can later be compared to the .iso, or a block device, using the corresponding \fBcheckisomd5\fR command. +.SH "OPTIONS" +.IP "\fB\-\-force\fP" 10 +Force an existing checksum to be overwritten. +.IP "\fB\-\-supported-iso\fP" 10 +Indicate that the image will be written to a "supported" media, such as pressed CD. On Red Hat-based Anaconda installers, this bypasses the prompt to check the CD. +.SH "SEE ALSO" +.PP +checkisomd5 (1). +.\" created by instant / docbook-to-man, Thu 07 Feb 2008, 12:11 diff --git a/implantisomd5.c b/implantisomd5.c new file mode 100644 index 0000000..759f841 --- /dev/null +++ b/implantisomd5.c @@ -0,0 +1,77 @@ +/* + * simple program to insert an md5sum into application data area of iso99660 + * Copyright (C) 2001-2007 Red Hat, Inc. + * Michael Fulbright + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "md5.h" +#include "libimplantisomd5.h" + + +static void usage(void) { + fprintf(stderr, "implantisomd5: implantisomd5 [--force] [--supported-iso] \n"); + exit(1); +} + + +int main(int argc, char **argv) { + int rc; + char *errstr; + const char **args; + + int forceit=0; + int supported=0; + int help=0; + + poptContext optCon; + struct poptOption options[] = { + { "force", 'f', POPT_ARG_NONE, &forceit, 0 }, + { "supported-iso", 'S', POPT_ARG_NONE, &supported, 0 }, + { "help", 'h', POPT_ARG_NONE, &help, 0}, + { 0, 0, 0, 0, 0} + }; + + + optCon = poptGetContext("implantisomd5", argc, (const char **)argv, options, 0); + + if ((rc = poptGetNextOpt(optCon)) < -1) { + fprintf(stderr, "bad option %s: %s\n", + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + poptStrerror(rc)); + exit(1); + } + + if (help) + usage(); + + args = poptGetArgs(optCon); + if (!args || !args[0] || !args[0][0]) + usage(); + + rc = implantISOFile((char *)args[0], supported, forceit, 0, &errstr); + if (rc) { + fprintf(stderr, "ERROR: "); + fprintf(stderr, errstr, (char *)args[0]); + exit(1); + } else { + exit(0); + } +} diff --git a/libcheckisomd5.c b/libcheckisomd5.c new file mode 100644 index 0000000..8bca842 --- /dev/null +++ b/libcheckisomd5.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2001-2007 Red Hat, Inc. + * + * Michael Fulbright + * Dustin Kirkland + * Added support for checkpoint fragment sums; + * Exits media check as soon as bad fragment md5sum'ed + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "md5.h" +#include "libcheckisomd5.h" + +#define APPDATA_OFFSET 883 +#define SIZE_OFFSET 84 + +/* Length in characters of string used for fragment md5sum checking */ +#define FRAGMENT_SUM_LENGTH 60 + +#define MAX(x, y) ((x > y) ? x : y) +#define MIN(x, y) ((x < y) ? x : y) + +/* finds primary volume descriptor and returns info from it */ +/* mediasum must be a preallocated buffer at least 33 bytes long */ +/* fragmentsums must be a preallocated buffer at least FRAGMENT_SUM_LENGTH+1 bytes long */ +static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported, char *fragmentsums, long long *fragmentcount) { + unsigned char buf[2048]; + char buf2[512]; + char tmpbuf[512]; + int skipfnd, md5fnd, supportedfnd, fragsumfnd, fragcntfnd; + unsigned int loc; + long long offset; + char *p; + + if (lseek(isofd, (off_t)(16L * 2048L), SEEK_SET) == -1) + return ((long long)-1); + + offset = (16L * 2048L); + for (;1;) { + if (read(isofd, buf, 2048) <= 0) + return ((long long)-1); + + if (buf[0] == 1) + /* found primary volume descriptor */ + break; + else if (buf[0] == 255) + /* hit end and didn't find primary volume descriptor */ + return ((long long)-1); + offset += 2048L; + } + + /* read out md5sum */ + memcpy(buf2, buf + APPDATA_OFFSET, 512); + buf2[511] = '\0'; + + *supported = 0; + + md5fnd = 0; + skipfnd = 0; + fragsumfnd = 0; + fragcntfnd = 0; + supportedfnd = 0; + loc = 0; + while (loc < 512) { + if (!strncmp(buf2 + loc, "ISO MD5SUM = ", 13)) { + + /* make sure we dont walk off end */ + if ((loc + 32 + 13) > 511) + return -1; + + memcpy(mediasum, buf2 + loc + 13, 32); + mediasum[32] = '\0'; + md5fnd = 1; + loc += 45; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "SKIPSECTORS = ", 14)) { + char *errptr; + + /* make sure we dont walk off end */ + if ((loc + 14) > 511) + return -1; + + loc = loc + 14; + for (p=tmpbuf; buf2[loc] != ';' && loc < 512; p++, loc++) + *p = buf2[loc]; + + *p = '\0'; + + *skipsectors = strtol(tmpbuf, &errptr, 10); + if (errptr && *errptr) { + return -1; + } else { + skipfnd = 1; + } + + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=1", 14)) { + *supported = 1; + supportedfnd = 1; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=0", 14)) { + *supported = 0; + supportedfnd = 1; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT SUMS = ", 16)) { + /* make sure we dont walk off end */ + if ((loc + FRAGMENT_SUM_LENGTH) > 511) + return -1; + + memcpy(fragmentsums, buf2 + loc + 16, FRAGMENT_SUM_LENGTH); + fragmentsums[FRAGMENT_SUM_LENGTH] = '\0'; + fragsumfnd = 1; + loc += FRAGMENT_SUM_LENGTH + 16; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT COUNT = ", 17)) { + char *errptr; + /* make sure we dont walk off end */ + if ((loc + 17) > 511) + return -1; + + loc = loc + 17; + for (p=tmpbuf; buf2[loc] != ';' && loc < 512; p++, loc++) + *p = buf2[loc]; + + *p = '\0'; + + *fragmentcount = strtol(tmpbuf, &errptr, 10); + if (errptr && *errptr) { + return -1; + } else { + fragcntfnd = 1; + } + + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else { + loc++; + } + + if ((skipfnd & md5fnd & fragsumfnd & fragcntfnd) & supportedfnd) + break; + } + + if (!(skipfnd & md5fnd)) + return -1; + + /* get isosize */ + *isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 + + buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL; + + return offset; +} + +/* mediasum is the sum encoded in media, computedsum is one we compute */ +/* both strings must be pre-allocated at least 33 chars in length */ +static int checkmd5sum(int isofd, char *mediasum, char *computedsum, checkCallback cb, void *cbdata) { + int nread; + int i, j; + int appdata_start_offset, appdata_end_offset; + int nattempt; + int skipsectors; + int supported; + int current_fragment = 0; + int previous_fragment = 0; + unsigned int bufsize = 32768; + unsigned char md5sum[16]; + unsigned char fragmd5sum[16]; + unsigned int len; + unsigned char *buf; + long long isosize, offset, pvd_offset, apoff; + char fragmentsums[FRAGMENT_SUM_LENGTH+1]; + char thisfragsum[FRAGMENT_SUM_LENGTH+1]; + long long fragmentcount = 0; + MD5_CTX md5ctx, fragmd5ctx; + + if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported, fragmentsums, &fragmentcount)) < 0) + return ISOMD5SUM_CHECK_NOT_FOUND; + + /* printf("Mediasum = %s\n",mediasum); */ + + /* rewind, compute md5sum */ + lseek(isofd, 0L, SEEK_SET); + + MD5_Init(&md5ctx); + + offset = 0; + apoff = pvd_offset + APPDATA_OFFSET; + + buf = malloc(bufsize * sizeof(unsigned char)); + if (cb) + cb(cbdata, 0, isosize - skipsectors*2048); + + while (offset < isosize - skipsectors*2048) { + nattempt = MIN(isosize - skipsectors*2048 - offset, bufsize); + + /* printf("%lld %lld %lld %d\n", offset, isosize, isosize-SKIPSECTORS*2048, nattempt); */ + + nread = read(isofd, buf, nattempt); + if (nread <= 0) + break; + + if (nread > nattempt) { + nread = nattempt; + lseek(isofd, offset+nread, SEEK_SET); + } + /* overwrite md5sum we implanted with original data */ + if (offset < apoff && offset+nread >= apoff) { + appdata_start_offset = apoff - offset; + appdata_end_offset = MIN(appdata_start_offset+MIN(nread, 512), + offset + nread - apoff); + len = appdata_end_offset - appdata_start_offset; + memset(buf+appdata_start_offset, ' ', len); + } else if (offset >= apoff && offset+nread < apoff + 512) { + appdata_start_offset = 0; + appdata_end_offset = nread; + len = appdata_end_offset - appdata_start_offset; + memset(buf+appdata_start_offset, ' ', len); + } else if (offset < apoff + 512 && offset+nread >= apoff + 512) { + appdata_start_offset = 0; + appdata_end_offset = apoff + 512 - offset; + len = appdata_end_offset - appdata_start_offset; + memset(buf+appdata_start_offset, ' ', len); + } + + MD5_Update(&md5ctx, buf, nread); + if (fragmentcount) { + current_fragment = offset * (fragmentcount+1) / (isosize - skipsectors*2048); + /* if we're onto the next fragment, calculate the previous sum and check */ + if ( current_fragment != previous_fragment ) { + memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); + MD5_Final(fragmd5sum, &fragmd5ctx); + *computedsum = '\0'; + j = (current_fragment-1)*FRAGMENT_SUM_LENGTH/fragmentcount; + for (i=0; i 0) && (fragmentcount > 0) ) { + printf("Fragment sums: %s\n", fragmentsums); + printf("Fragment count: %lld\n", fragmentcount); + } + + return 0; +} diff --git a/libcheckisomd5.h b/libcheckisomd5.h new file mode 100644 index 0000000..78213d1 --- /dev/null +++ b/libcheckisomd5.h @@ -0,0 +1,16 @@ +#ifndef __LIBCHECKISOMD5_H__ +#define __LIBCHECKISOMD5_H__ + +#define ISOMD5SUM_CHECK_PASSED 1 +#define ISOMD5SUM_CHECK_FAILED 0 +#define ISOMD5SUM_CHECK_ABORTED 2 +#define ISOMD5SUM_CHECK_NOT_FOUND -1 +#define ISOMD5SUM_FILE_NOT_FOUND -2 + +/* for non-zero return value, check is aborted */ +typedef int (*checkCallback)(void *, long long offset, long long total); + +int mediaCheckFile(char *iso, checkCallback cb, void *cbdata); +int printMD5SUM(char *file); + +#endif diff --git a/libimplantisomd5.c b/libimplantisomd5.c new file mode 100644 index 0000000..4009809 --- /dev/null +++ b/libimplantisomd5.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2001-2007 Red Hat, Inc. + * + * Michael Fulbright + * Dustin Kirkland + * Added support for checkpoint fragment sums; + * Exits media check as soon as bad fragment md5sum'ed + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "md5.h" +#include "libimplantisomd5.h" + +#define APPDATA_OFFSET 883 +#define SIZE_OFFSET 84 + +/* Length in characters of string used for fragment md5sum checking */ +#define FRAGMENT_SUM_LENGTH 60 +/* FRAGMENT_COUNT must be an integral divisor or FRAGMENT_SUM_LENGTH */ +/* 60 => 2, 3, 4, 5, 6, 10, 12, 15, 20, or 30 */ +#define FRAGMENT_COUNT 20 + +/* number of sectors to ignore at end of iso when computing sum */ +#define SKIPSECTORS 15 + +#define MAX(x, y) ((x > y) ? x : y) +#define MIN(x, y) ((x < y) ? x : y) + +/* finds primary volume descriptor and returns info from it */ +/* mediasum must be a preallocated buffer at least 33 bytes long */ +static int parsepvd(int isofd, char *mediasum, long long *isosize) { + unsigned char buf[2048]; + long long offset; + unsigned char *p __attribute__((unused)); + + if (lseek(isofd, 16*2048, SEEK_SET) == -1) + return ((long long)-1); + + offset = (16 * 2048); + for (;1;) { + if (read(isofd, buf, 2048L) == -1) + return ((long long)-1); + + if (buf[0] == 1) + /* found primary volume descriptor */ + break; + else if (buf[0] == 255) + /* hit end and didn't find primary volume descriptor */ + return ((long long)-1); + offset += 2048L; + } + + /* read out md5sum */ +#if 0 + memcpy(mediasum, buf + APPDATA_OFFSET + 13, 32); + mediasum[32] = '\0'; + + for (p=mediasum; *p; p++) + if (*p != ' ') + break; + + /* if the md5sum was all spaces, we didn't find md5sum */ + if (!*p) + return -1; +#endif + + /* get isosize */ + *isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 + + buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL; + + return offset; +} + + +static unsigned int writeAppData(unsigned char *appdata, char *valstr, unsigned int loc) { + if (loc + strlen(valstr) > 511) { + printf("Attempted to write too much appdata, exiting...\n"); + exit(-1); + } + + memcpy(appdata + loc, valstr, strlen(valstr)); + + return loc+strlen(valstr); +} + + + + +int implantISOFile(char *fname, int supported, int forceit, int quiet, char **errstr) { + int i; + int isofd; + int nread; + int dirty; + int pvd_offset; + int current_fragment = 0; + int previous_fragment = 0; + int nattempt; + long long isosize, total; + unsigned char md5sum[16]; + unsigned char fragmd5sum[16]; + unsigned int loc; + unsigned int bufsize = 32768; + unsigned char *buf; + unsigned char orig_appdata[512]; + unsigned char new_appdata[512]; + char mediasum[33]; + char md5str[40]; + char fragstr[FRAGMENT_SUM_LENGTH+1]; + MD5_CTX md5ctx, fragmd5ctx; + + isofd = open(fname, O_RDWR); + + if (isofd < 0) { + *errstr = "Error - Unable to open file %s\n\n"; + return -1; + } + + pvd_offset = parsepvd(isofd, mediasum, &isosize); + if (pvd_offset < 0) { + *errstr = "Could not find primary volumne!\n\n"; + return -1; + } + + lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET); + nread = read(isofd, orig_appdata, 512); + + if (!forceit) { + dirty = 0; + for (i=0; i < 512; i++) + if (orig_appdata[i] != ' ') + dirty = 1; + + if (dirty) { + *errstr = "Application data has been used - not implanting md5sum!\n"; + return -1; + } + } else { + /* write out blanks to erase old app data */ + lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET); + memset(new_appdata, ' ', 512); + i = write(isofd, new_appdata, 512); + if (i<0) { + printf("write failed %d\n", i); + perror(""); + } + } + + /* now do md5sum */ + lseek(isofd, 0L, SEEK_SET); + + MD5_Init(&md5ctx); + *fragstr = '\0'; + buf = malloc(bufsize * sizeof(unsigned char)); + + total = 0; + /* read up to 15 sectors from end, due to problems reading last few */ + /* sectors on burned CDs */ + while (total < isosize - SKIPSECTORS*2048) { + nattempt = MIN(isosize - SKIPSECTORS*2048 - total, bufsize); + nread = read(isofd, buf, nattempt); + + if (nread <= 0) + break; + + MD5_Update(&md5ctx, buf, nread); + + /* if we're onto the next fragment, calculate the previous sum and write */ + current_fragment = total * (FRAGMENT_COUNT+1) / (isosize - SKIPSECTORS*2048); + if ( current_fragment != previous_fragment ) { + memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); + MD5_Final(fragmd5sum, &fragmd5ctx); + for (i=0; i to handle + * endianness better + * + */ + +#include +#include +#include "md5.h" + +void MD5_Transform(uint32 *buf, uint32 const *in); + +#define IS_BIG_ENDIAN() (__BYTE_ORDER == __BIG_ENDIAN) +#define IS_LITTLE_ENDIAN() (__BYTE_ORDER == __LITTLE_ENDIAN) + +static void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5_Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301U; + ctx->buf[1] = 0xefcdab89U; + ctx->buf[2] = 0x98badcfeU; + ctx->buf[3] = 0x10325476U; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; + + + if (IS_BIG_ENDIAN()) + ctx->doByteReverse = 1; + else + ctx->doByteReverse = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5_Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + if (ctx->doByteReverse) byteReverse(ctx->in, 16); + MD5_Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + if (ctx->doByteReverse) byteReverse(ctx->in, 16); + MD5_Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5_Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + if (ctx->doByteReverse) byteReverse(ctx->in, 16); + MD5_Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + if (ctx->doByteReverse) byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5_Transform(ctx->buf, (uint32 *) ctx->in); + if (ctx->doByteReverse) byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5_Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..fd4ea0e --- /dev/null +++ b/md5.h @@ -0,0 +1,26 @@ + +#ifndef MD5_H +#define MD5_H + +#include + +typedef u_int32_t uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; + int doByteReverse; +}; + +void MD5_Init(struct MD5Context *); +void MD5_Update(struct MD5Context *, unsigned const char *, unsigned); +void MD5_Final(unsigned char digest[16], struct MD5Context *); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ + +typedef struct MD5Context MD5_CTX; + +#endif /* MD5_H */ diff --git a/pyisomd5sum.c b/pyisomd5sum.c new file mode 100644 index 0000000..a0c40da --- /dev/null +++ b/pyisomd5sum.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2001-2007 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "libcheckisomd5.h" +#include "libimplantisomd5.h" + +static PyObject * doCheckIsoMD5Sum(PyObject * s, PyObject * args); +static PyObject * doImplantIsoMD5Sum(PyObject * s, PyObject * args); + +static PyMethodDef isomd5sumMethods[] = { + { "checkisomd5sum", (PyCFunction) doCheckIsoMD5Sum, METH_VARARGS, NULL }, + { "implantisomd5sum", (PyCFunction) doImplantIsoMD5Sum, METH_VARARGS, NULL }, + { NULL } +} ; + + +static PyObject * doCheckIsoMD5Sum(PyObject * s, PyObject * args) { + char *isofile; + int rc; + + if (!PyArg_ParseTuple(args, "s", &isofile)) + return NULL; + + rc = mediaCheckFile(isofile, NULL, NULL); + + return Py_BuildValue("i", rc); +} + +static PyObject * doImplantIsoMD5Sum(PyObject * s, PyObject * args) { + char *isofile, *errstr; + int forceit, supported; + int rc; + + if (!PyArg_ParseTuple(args, "sii", &isofile, &supported, &forceit)) + return NULL; + + rc = implantISOFile(isofile, supported, forceit, 1, &errstr); + + return Py_BuildValue("i", rc); +} + + +void initpyisomd5sum(void) { + PyObject * m, * d; + + m = Py_InitModule("pyisomd5sum", isomd5sumMethods); + d = PyModule_GetDict(m); +} diff --git a/testpyisomd5sum.py b/testpyisomd5sum.py new file mode 100755 index 0000000..6f79830 --- /dev/null +++ b/testpyisomd5sum.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +import os +import pyisomd5sum + +# create iso file +os.system("mkisofs -quiet . > testiso.iso") + +# implant it +print "Implanting -> ", pyisomd5sum.implantisomd5sum("testiso.iso", 1, 0) + +# do it again without forcing, should get error +print "Implanting again w/o forcing -> ", pyisomd5sum.implantisomd5sum("testiso.iso", 1, 0) + +# do it again with forcing, should work +print "Implanting again forcing -> ", pyisomd5sum.implantisomd5sum("testiso.iso", 1, 1) + +# check it +print "Checking -> ",pyisomd5sum.checkisomd5sum("testiso.iso") + +# clean up +os.unlink("testiso.iso")