diff --git a/COMMERCIAL b/COMMERCIAL new file mode 100644 index 0000000..5bfad07 --- /dev/null +++ b/COMMERCIAL @@ -0,0 +1,6 @@ + +If you desire enterprise capable software with commercial support, check out +Tripwire, Inc. at http://www.tripwire.com. + +For a more detailed comparison of the Open Source Tripwire software and +commercial Tripwire(R) product(s) please visit http://www.tripwire.org. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..12992c2 --- /dev/null +++ b/COPYING @@ -0,0 +1,372 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + --------------------------- + + Tripwire Trademark Information + +The developer of the original code and/or files is Tripwire, Inc. Portions +created by Tripwire, Inc. are copyright 2000 Tripwire, Inc. Tripwire is a +registered trademark of Tripwire, Inc. All rights reserved. + +This program is free software. The contents of this file are subject to 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. You may redistribute it and/or modify it only in compliance with the +GNU General Public License. + +This program is distributed in the hope that it will be useful. However, this +program is distributed "AS-IS" WITHOUT ANY WARRANTY; INCLUDING THE IMPLIED +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please 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. + +Nothing in the GNU General Public License or any other license to use the code +or files shall permit you to use Tripwire's trademarks, service marks, or +other intellectual property without Tripwire's prior written consent. + +If you have any questions, please contact Tripwire, Inc. at either +info@tripwire.org or www.tripwire.org. + + End of Tripwire Trademark Information + --------------------------------------------- + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/ChangeLog b/ChangeLog new file mode 100644 index 0000000..469c352 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,86 @@ +2011-11-21 Stephane Dudzinski + + * Bumping version to 2.4.2.2 + * Updated version revision in reports and all + * Added experimental policy creation (see policy/policy_generator_readme.txt) + * Fixed report formating and sendmail issues + * Added Debian patches for crypto and hostnames + * Fixed compiling issue on recent GCC compilers (-fpermissive) + +2011-07-14 Stephane Dudzinski + + * Bumping version to 2.4.2.1 + * Fixed version numbering and added RPM spec file + +2010-03-11 Stephane Dudzinski + + * Bumping version to 2.4.2 + * Added patch to fix bug [ 1962485 ] Cannot change or expect-script + passphrases - thanks to Ross Tyler (rtyle) + * Removed RPM spec file for now, will be fixed in next release + +2007-04-16 Ron Forrester + + * Bumping all versions to 2.4.1.2 + * Fixed bug in install script when sendmail isn't installed + target system. + * Removed some non-existent files from installer + +2005-08-18 Ron Forrester + + * Wow, has it been 4+ years? :) + + * Starting fresh with Paul's autoconf'ed code base + + * Bumped version number, misc cleanup, etc. + + +2001-02-25 Ron Forrester + + * Bumped version to 2.3.1. + + * BSD support, thanks to Paul Herman . + The support was added for FreeBSD 4.2, your mileage may vary on + other BSD's. + + * Fixed long standing bug with recurse=3 + + * If TEMPDIRECTORY was missing trailing /, bad things could + happen. Tripwire now appends a / if one isn't present. Thanks + Jarno. + + * Fixed GLOBALEMAIL bug where no global emails would be sent + unless there were emailto attributes somewhere in the policy + file. Additionally, reports were being sliced to global + recipients, despite the fact that global recipients should get + the full report. + + +2001-02-03 Ron Forrester + + * Fixed possible security problem with the handling of temp + files. We now open temp files with O_EXCL set to make sure a + particular file doesn't already exist. Thanks to Jarno for this + suggestion and help via a patch. + + * Added the configuration file variable TEMPDIRECTORY. This + variable can be set to the full path to where tripwire should + write its temporary files. By default it is /tmp. Because /tmp has + to be world writable, this isn't a good place for tripwire to + write temporary files. Setting TEMPDIRECTORY to a directory with + permissions 700 is much more secure. Updated man page with info on + this variable. + + * Added the configuration file variable GLOBALEMAIL. This variable + can be set to a list of email addresses which are semi-colon or + comma separated. If a report is about to be emailed to addresses + reaped from the policy file, it will also be emailed to the + addresses in the GLOBALEMAIL list, allowing designation of one or + more people to always get email reports. Updated the man page with + info on this variable. + + * Began a convention of providing a "Solution:" line to all errors + (exceptions) emitted by tripwire. Only the two latest error + messages incorporate this convention, but all future ones will as + well, and I hope to revist all current errors and retrofit them + with Solution: lines as well. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..9618a23 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,19 @@ +Open Source Tripwire Maintainers: + +tripwire@frlinux.net + +Previous Maintainer: + +itripn@users.sourceforge.net + + +Community Contributors: + +Paul Herman (www.frenchfries.net/paul/tripwire): Paul is almost solely +responsible for the meat of the 2.4.0.1 release. His work on the autoconf +and gcc 3.x support (among other things) has contributed to a much more +portable code base, and an easier place to start for adding additional +features. + +David LaPalomento: David kindly provided precompiled binaries on Red Hat +Enterprise Linux AS release 4 (Nahant Update 3) on IA-64. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..ed67023 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +SUBDIRS = man src + +install-data-hook: + prefix="$(prefix)" sysconfdir="$(sysconfdir)" \ + path_to_vi="$(path_to_vi)" path_to_sendmail="$(path_to_sendmail)" \ + ./install/install.sh diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..9b3e1cf --- /dev/null +++ b/Makefile.in @@ -0,0 +1,597 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure COPYING ChangeLog INSTALL config.guess \ + config.sub install-sh ltmain.sh missing mkinstalldirs +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno configure.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +SUBDIRS = man src +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ + cd $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || mkdir "$(distdir)/$$subdir" \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="../$(top_distdir)" \ + distdir="../$(distdir)/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + $(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + $(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(AMTAR) xf - ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ + check-am clean clean-generic clean-recursive ctags \ + ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \ + dist-tarZ dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-recursive distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive \ + mostlyclean mostlyclean-generic mostlyclean-recursive pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-info-am + + +install-data-hook: + prefix="$(prefix)" sysconfdir="$(sysconfdir)" \ + path_to_vi="$(path_to_vi)" path_to_sendmail="$(path_to_sendmail)" \ + ./install/install.sh +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/TRADEMARK b/TRADEMARK new file mode 100644 index 0000000..e06b19a --- /dev/null +++ b/TRADEMARK @@ -0,0 +1,18 @@ +TRIPWIRE COPYRIGHT & TRADEMARK NOTICE + +COPYRIGHT +The developer of the original code and/or files is Tripwire, Inc. Portions +created by Tripwire, Inc. are copyright 2000 Tripwire, Inc. + +TRADEMARK +Tripwire is a registered trademark (the "Trademark") of Tripwire, Inc. All +rights reserved. + +The GNU General Public License permits you to use the original code and/or +files created by Tripwire. Nothing in the GNU General Public License or any +other license shall permit you to use the Trademark. If you commercially +distribute or modify the code and/or files, you must obtain Tripwire's prior +written consent to use or reproduce the Trademark. + +If you have any questions, please contact Tripwire, Inc. at +info@tripwire.com. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..7c021bf --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,932 @@ +# generated automatically by aclocal 1.8.5 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# -*- Autoconf -*- +# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# Generated from amversion.in; do not edit by hand. + +# 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, 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 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.8.5])]) + +# AM_AUX_DIR_EXPAND + +# Copyright (C) 2001, 2003 Free Software Foundation, 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, 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, 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, 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. + +# serial 6 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]) +fi])]) + +# serial 7 -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 +# Free Software Foundation, 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, 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. + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, 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, 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. + +#serial 2 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, 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, 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. + +# serial 7 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# This macro actually does too much some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, 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, 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. + +# serial 11 + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.58])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl + +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. + +# Copyright (C) 2001, 2003 Free Software Foundation, 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, 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. + +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# -*- Autoconf -*- +# Copyright (C) 2003 Free Software Foundation, 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, 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. + +# serial 1 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, 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, 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. + +# serial 2 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# -*- Autoconf -*- + + +# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, 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, 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. + +# serial 3 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# AM_PROG_MKDIR_P +# --------------- +# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. + +# Copyright (C) 2003, 2004 Free Software Foundation, 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, 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. + +# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories +# created by `make install' are always world readable, even if the +# installer happens to have an overly restrictive umask (e.g. 077). +# This was a mistake. There are at least two reasons why we must not +# use `-m 0755': +# - it causes special bits like SGID to be ignored, +# - it may be too restrictive (some setups expect 775 directories). +# +# Do not use -m 0755 and let people choose whatever they expect by +# setting umask. +# +# We cannot accept any implementation of `mkdir' that recognizes `-p'. +# Some implementations (such as Solaris 8's) are not thread-safe: if a +# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' +# concurrently, both version can detect that a/ is missing, but only +# one can create it and the other will error out. Consequently we +# restrict ourselves to GNU make (using the --version option ensures +# this.) +AC_DEFUN([AM_PROG_MKDIR_P], +[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # Keeping the `.' argument allows $(mkdir_p) to be used without + # argument. Indeed, we sometimes output rules like + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. + # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more + # expensive solution, as it forces Make to start a sub-shell.) + mkdir_p='mkdir -p -- .' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi +AC_SUBST([mkdir_p])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, 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, 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. + +# serial 2 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# +# Check to make sure that the build environment is sane. +# + +# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, 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, 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. + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# AM_PROG_INSTALL_STRIP + +# Copyright (C) 2001, 2003 Free Software Foundation, 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, 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. + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + diff --git a/bin/.fix b/bin/.fix new file mode 100644 index 0000000..8b0cb99 --- /dev/null +++ b/bin/.fix @@ -0,0 +1 @@ +needed diff --git a/config.guess b/config.guess new file mode 100644 index 0000000..6012b39 --- /dev/null +++ b/config.guess @@ -0,0 +1,1298 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-07-12' + +# This file 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# Please send patches to . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # Netbsd (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-unknown ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE}" in + i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + case "${HPUX_REV}" in + 11.[0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + esac ;; + esac + fi ;; + esac + if [ "${HP_ARCH}" = "" ]; then + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + eval $set_cc_for_build + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in + big) echo mips-unknown-linux-gnu && exit 0 ;; + little) echo mipsel-unknown-linux-gnu && exit 0 ;; + esac + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev67 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_supported_targets=`cd /; ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-pc-linux-gnu\n", argv[1]); +# else + printf ("%s-pc-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-pc-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-pc-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[KW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +eval $set_cc_for_build +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..dfa37fd --- /dev/null +++ b/config.h.in @@ -0,0 +1,173 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Compile with debug code */ +#undef DEBUG + +/* this is the prefix for STL exception functions */ +#undef EXCEPTION_NAMESPACE + +/* Define to 1 if you have the header file. */ +#undef HAVE_BITS_SIGNUM_H + +/* Uses the GNU gcc compiler */ +#undef HAVE_GCC + +/* Define to 1 if you have the `gethostid' function. */ +#undef HAVE_GETHOSTID + +/* Define to 1 if you have the `gethostname' function. */ +#undef HAVE_GETHOSTNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_ICONV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LANGINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_MD5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SHA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNUM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSMACROS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_USTAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_VARARGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Is byte aligned */ +#undef IS_BYTE_ALIGNED + +/* Is a unix type platform */ +#undef IS_UNIX + +/* don't generate debuging code */ +#undef NDEBUG + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* Don't use gethostbyname() on Solaris */ +#undef SOLARIS_NO_GETHOSTBYNAME + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Target OS */ +#undef TARGET_OS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Uses one's complement */ +#undef USES_1S_COMPLEMENT + +/* Uses two's complement */ +#undef USES_2S_COMPLEMENT + +/* Uses signed magnitute */ +#undef USES_SIGNED_MAGNITUDE + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/config.sub b/config.sub new file mode 100644 index 0000000..578b302 --- /dev/null +++ b/config.sub @@ -0,0 +1,1375 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-06-08' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ + | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ + | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp10 | pdp11 \ + | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ + | v850 | c4x \ + | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ + | pj | pjl | h8500 | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ + | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \ + | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ + | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ + | [cjt]90-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [cjt]90) + basic_machine=${basic_machine}-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4) + basic_machine=sh-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..15c99aa --- /dev/null +++ b/configure @@ -0,0 +1,11966 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/tw/tw.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +CYGPATH_W +PACKAGE +VERSION +ACLOCAL +AUTOCONF +AUTOMAKE +AUTOHEADER +MAKEINFO +AMTAR +install_sh +STRIP +INSTALL_STRIP_PROGRAM +mkdir_p +AWK +SET_MAKE +am__leading_dot +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +DEPDIR +am__include +am__quote +AMDEP_TRUE +AMDEP_FALSE +AMDEPBACKSLASH +CCDEPMODE +am__fastdepCC_TRUE +am__fastdepCC_FALSE +CXX +CXXFLAGS +ac_ct_CXX +CXXDEPMODE +am__fastdepCXX_TRUE +am__fastdepCXX_FALSE +RANLIB +YACC +YFLAGS +path_to_vi +path_to_sendmail +CPP +GREP +EGREP +CXXCPP +CORE_CRYPT_O +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CXX +CXXFLAGS +CCC +YACC +YFLAGS +CPP +CXXCPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-static compile static binaries + --enable-debug compile with debuging enabled + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --disable-openssl don't link against OpenSSL libraries + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-ssl-dir=PATH Specify path to OpenSSL installation + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + YACC The `Yet Another C Compiler' implementation to use. Defaults to + the first program found out of: `bison -y', `byacc', `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + CPP C preprocessor + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.60 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.60. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- +am__api_version="1.8" +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm -f conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # Keeping the `.' argument allows $(mkdir_p) to be used without + # argument. Indeed, we sometimes output rules like + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. + # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more + # expensive solution, as it forces Make to start a sub-shell.) + mkdir_p='mkdir -p -- .' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE=tripwire + VERSION=2.4.2.2 + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. + + + +ac_config_headers="$ac_config_headers config.h" + + +rm -f src/tripwire/syslog.h 2> /dev/null +chmod 755 install-sh 2> /dev/null + +CFLAGS=${CFLAGS:-"-O -pipe -Wall -Wno-non-virtual-dtor"} +CXXFLAGS=${CXXFLAGS:-"-O -pipe -Wall -Wno-non-virtual-dtor"} + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then + enableval=$enable_static; +fi + +if test "x$enable_static" = xyes +then LDFLAGS="${LDFLAGS} -static" +fi +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then + enableval=$enable_debug; +fi + +if test "x$enable_debug" = xyes +then + CFLAGS="${CFLAGS} -g" + CXXFLAGS="${CXXFLAGS} -g" + +cat >>confdefs.h <<\_ACEOF +#define DEBUG 1 +_ACEOF + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +{ echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_YACC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_YACC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { echo "$as_me:$LINENO: result: $YACC" >&5 +echo "${ECHO_T}$YACC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +# Extract the first word of "vi", so it can be a program name with args. +set dummy vi; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_path_to_vi+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $path_to_vi in + [\\/]* | ?:[\\/]*) + ac_cv_path_path_to_vi="$path_to_vi" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_path_to_vi="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +path_to_vi=$ac_cv_path_path_to_vi +if test -n "$path_to_vi"; then + { echo "$as_me:$LINENO: result: $path_to_vi" >&5 +echo "${ECHO_T}$path_to_vi" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "sendmail", so it can be a program name with args. +set dummy sendmail; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_path_to_sendmail+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $path_to_sendmail in + [\\/]* | ?:[\\/]*) + ac_cv_path_path_to_sendmail="$path_to_sendmail" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="$PATH:/usr/libexec" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_path_to_sendmail="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_path_to_sendmail" && ac_cv_path_path_to_sendmail="""" + ;; +esac +fi +path_to_sendmail=$ac_cv_path_path_to_sendmail +if test -n "$path_to_sendmail"; then + { echo "$as_me:$LINENO: result: $path_to_sendmail" >&5 +echo "${ECHO_T}$path_to_sendmail" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +if test "x${GXX}" != "x"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GCC 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GCC 0 +_ACEOF + +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in sys/param.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in sys/mount.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined(HAVE_SYS_PARAM_H) +#include +#endif + + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in sys/ustat.h sys/sysmacros.h sys/syslog.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + +for ac_header in unistd.h syslog.h iconv.h langinfo.h sys/statfs.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in signum.h bits/signum.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +fi + +done + + + +for ac_header in stdarg.h varargs.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +fi + +done + + +CPPFLAGS_SAVE="${CPPFLAGS}" +CPPFLAGS="${CPPFLAGS} -Werror" + +for ac_header in malloc.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +CPPFLAGS="${CPPFLAGS_SAVE}" + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !x[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef size_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6; } +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_bigendian=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +{ echo "$as_me:$LINENO: checking for int" >&5 +echo $ECHO_N "checking for int... $ECHO_C" >&6; } +if test "${ac_cv_type_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef int ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_int=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 +echo "${ECHO_T}$ac_cv_type_int" >&6; } + +{ echo "$as_me:$LINENO: checking size of int" >&5 +echo $ECHO_N "checking size of int... $ECHO_C" >&6; } +if test "${ac_cv_sizeof_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_int" = yes; then + # The cast to long int works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo= ac_hi= +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr '(' $ac_mid ')' + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_int=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef int ac__type_sizeof_; +static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } +static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (((long int) (sizeof (ac__type_sizeof_))) < 0) + { + long int i = longval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%ld\n", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%lu\n", i); + } + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_int=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.val +else + ac_cv_sizeof_int=0 +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 +echo "${ECHO_T}$ac_cv_sizeof_int" >&6; } +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +{ echo "$as_me:$LINENO: checking for long" >&5 +echo $ECHO_N "checking for long... $ECHO_C" >&6; } +if test "${ac_cv_type_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef long ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_long=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 +echo "${ECHO_T}$ac_cv_type_long" >&6; } + +{ echo "$as_me:$LINENO: checking size of long" >&5 +echo $ECHO_N "checking size of long... $ECHO_C" >&6; } +if test "${ac_cv_sizeof_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_long" = yes; then + # The cast to long int works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo= ac_hi= +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr '(' $ac_mid ')' + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long ac__type_sizeof_; +static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } +static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (((long int) (sizeof (ac__type_sizeof_))) < 0) + { + long int i = longval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%ld\n", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%lu\n", i); + } + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.val +else + ac_cv_sizeof_long=0 +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long" >&6; } +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +{ echo "$as_me:$LINENO: checking for long long" >&5 +echo $ECHO_N "checking for long long... $ECHO_C" >&6; } +if test "${ac_cv_type_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef long long ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_long_long=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 +echo "${ECHO_T}$ac_cv_type_long_long" >&6; } + +{ echo "$as_me:$LINENO: checking size of long long" >&5 +echo $ECHO_N "checking size of long long... $ECHO_C" >&6; } +if test "${ac_cv_sizeof_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_long_long" = yes; then + # The cast to long int works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo= ac_hi= +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr '(' $ac_mid ')' + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_long_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long long) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } ;; +esac +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + typedef long long ac__type_sizeof_; +static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } +static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (((long int) (sizeof (ac__type_sizeof_))) < 0) + { + long int i = longval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%ld\n", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ((long int) (sizeof (ac__type_sizeof_)))) + return 1; + fprintf (f, "%lu\n", i); + } + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long long) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.val +else + ac_cv_sizeof_long_long=0 +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6; } +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + + + +cat >>confdefs.h <<\_ACEOF +#define USES_1S_COMPLEMENT 0 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define USES_2S_COMPLEMENT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define USES_SIGNED_MAGNITUDE 0 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define IS_BYTE_ALIGNED 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define EXCEPTION_NAMESPACE std:: +_ACEOF + + + +cat >>confdefs.h <<\_ACEOF +#define IS_UNIX 1 +_ACEOF + + + +cat >>confdefs.h <<\_ACEOF +#define NDEBUG 1 +_ACEOF + + + + + +for ac_func in strftime gethostname gethostid +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +for ac_func in mkstemp mktemp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +{ echo "$as_me:$LINENO: checking for socket in -lc" >&5 +echo $ECHO_N "checking for socket in -lc... $ECHO_C" >&6; } +if test "${ac_cv_lib_c_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_socket=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_socket=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_socket" >&5 +echo "${ECHO_T}$ac_cv_lib_c_socket" >&6; } +if test $ac_cv_lib_c_socket = yes; then + : +else + + { echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 +echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6; } +if test "${ac_cv_lib_socket_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_socket=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_socket=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6; } +if test $ac_cv_lib_socket_socket = yes; then + + LIBS="-lsocket $LIBS" + +else + : +fi + +fi + + +{ echo "$as_me:$LINENO: checking for gethostbyname in -lc" >&5 +echo $ECHO_N "checking for gethostbyname in -lc... $ECHO_C" >&6; } +if test "${ac_cv_lib_c_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_c_gethostbyname=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_c_gethostbyname" >&6; } +if test $ac_cv_lib_c_gethostbyname = yes; then + : +else + + { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nsl_gethostbyname=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } +if test $ac_cv_lib_nsl_gethostbyname = yes; then + + LIBS="-lnsl $LIBS" + +else + : +fi + +fi + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +if test "${ac_cv_header_locale+set}" = set; then + { echo "$as_me:$LINENO: checking for locale" >&5 +echo $ECHO_N "checking for locale... $ECHO_C" >&6; } +if test "${ac_cv_header_locale+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_locale" >&5 +echo "${ECHO_T}$ac_cv_header_locale" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking locale usability" >&5 +echo $ECHO_N "checking locale usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking locale presence" >&5 +echo $ECHO_N "checking locale presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: locale: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: locale: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: locale: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: locale: present but cannot be compiled" >&5 +echo "$as_me: WARNING: locale: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: locale: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: locale: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: locale: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: locale: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: locale: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: locale: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for locale" >&5 +echo $ECHO_N "checking for locale... $ECHO_C" >&6; } +if test "${ac_cv_header_locale+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_locale=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_locale" >&5 +echo "${ECHO_T}$ac_cv_header_locale" >&6; } + +fi +if test $ac_cv_header_locale = yes; then + : +else + + { echo "$as_me:$LINENO: checking for STLport directory" >&5 +echo $ECHO_N "checking for STLport directory... $ECHO_C" >&6; } +if test "${ac_cv_stlportdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + found_locale="" + for inclpath in /usr/local/include /usr/local/include/stlport + do + CPPFLAGS_save=${CPPFLAGS} + CPPFLAGS="${CPPFLAGS} -I${inclpath}" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include + + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + found_locale="1" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS=${CPPFLAGS_save} + if test "x${found_locale}" = "x1" + then + ac_cv_stlportdir=${inclpath} + break + fi + done + if test "x${found_locale}" = "x"; then + echo "not found" + { echo "$as_me:$LINENO: WARNING: + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + " >&5 +echo "$as_me: WARNING: + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + " >&2;} + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_stlportdir" >&5 +echo "${ECHO_T}$ac_cv_stlportdir" >&6; } + +fi + + + if test "x${ac_cv_stlportdir}" != "x" + then + CPPFLAGS="${CPPFLAGS} -I${ac_cv_stlportdir}" + fi + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: checking for pthread_getspecific" >&5 +echo $ECHO_N "checking for pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_func_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define pthread_getspecific to an innocuous variant, in case declares pthread_getspecific. + For example, HP-UX 11i declares gettimeofday. */ +#define pthread_getspecific innocuous_pthread_getspecific + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char pthread_getspecific (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef pthread_getspecific + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_pthread_getspecific || defined __stub___pthread_getspecific +choke me +#endif + +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_pthread_getspecific=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_pthread_getspecific=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_func_pthread_getspecific" >&6; } +if test $ac_cv_func_pthread_getspecific = yes; then + : +else + + + LDFLAGS_TEMP="${LDFLAGS}" + LDFLAGS="${LDFLAGS_TEMP} -pthread" + unset ac_cv_func_pthread_getspecific + { echo "$as_me:$LINENO: checking for pthread_getspecific" >&5 +echo $ECHO_N "checking for pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_func_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define pthread_getspecific to an innocuous variant, in case declares pthread_getspecific. + For example, HP-UX 11i declares gettimeofday. */ +#define pthread_getspecific innocuous_pthread_getspecific + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char pthread_getspecific (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef pthread_getspecific + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_pthread_getspecific || defined __stub___pthread_getspecific +choke me +#endif + +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_pthread_getspecific=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_pthread_getspecific=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_func_pthread_getspecific" >&6; } +if test $ac_cv_func_pthread_getspecific = yes; then + : +else + + + LDFLAGS="${LDFLAGS_TEMP} -lpthread" + unset ac_cv_func_pthread_getspecific + { echo "$as_me:$LINENO: checking for pthread_getspecific" >&5 +echo $ECHO_N "checking for pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_func_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define pthread_getspecific to an innocuous variant, in case declares pthread_getspecific. + For example, HP-UX 11i declares gettimeofday. */ +#define pthread_getspecific innocuous_pthread_getspecific + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char pthread_getspecific (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef pthread_getspecific + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_pthread_getspecific || defined __stub___pthread_getspecific +choke me +#endif + +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_pthread_getspecific=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_pthread_getspecific=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_func_pthread_getspecific" >&6; } +if test $ac_cv_func_pthread_getspecific = yes; then + : +else + + LDFLAGS="${LDFLAGS_TEMP}" + { { echo "$as_me:$LINENO: error: No posix threads detected, cannot continue." >&5 +echo "$as_me: error: No posix threads detected, cannot continue." >&2;} + { (exit 1); exit 1; }; } +fi + + +fi + + +fi + + + { echo "$as_me:$LINENO: checking for STLport library directory" >&5 +echo $ECHO_N "checking for STLport library directory... $ECHO_C" >&6; } +if test "${ac_cv_stlportlib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + found_lib="" + for inclpath in /usr/local/lib /usr/local/lib/stlport + do + for stllib in stlport stlport_gcc + do + LDFLAGS_save=${LDFLAGS} + LIBS_save=${LIBS} + LDFLAGS="${LDFLAGS} -L${inclpath}" + LIBS="${LIBS} -l${stllib}" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include + + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + found_lib="1" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=${LDFLAGS_save} + LIBS=${LIBS_save} + if test "x${found_lib}" = "x1" + then + ac_cv_stlportlib=${inclpath} + break + fi + done + if test "x${found_lib}" = "x1" + then + break + fi + done + if test "x${found_lib}" = "x"; then + echo "not found" + { echo "$as_me:$LINENO: WARNING: + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + " >&5 +echo "$as_me: WARNING: + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + " >&2;} + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_stlportlib" >&5 +echo "${ECHO_T}$ac_cv_stlportlib" >&6; } + if test "x${ac_cv_stlportdir}" != "x" + then + LDFLAGS="${LDFLAGS} -L${ac_cv_stlportlib}" + LIBS="${LIBS} -l${stllib}" + fi + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +for ac_header in wchar.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +cat >>confdefs.h <<_ACEOF +#define TARGET_OS "${target}" +_ACEOF + +case $target in + i386-*-freebsd*) + ;; + alpha-*-freebsd*) + ;; + i386-*-openbsd*) + ;; + *-*-netbsd*) + ;; + i[0-9]86-pc-linux*) + ;; + sparc-*-linux*) + ;; + *-sun-solaris*) + if test "x$enable_static" = xyes + then + { echo "$as_me:$LINENO: WARNING: + +Sorry, tripwire will not properly link staticaly under Solaris. +This is due to tripwire's extensive use of gethostbyname(), +which can only be linked dynamicaly. Please rerun configure +without the --enable-static option. +" >&5 +echo "$as_me: WARNING: + +Sorry, tripwire will not properly link staticaly under Solaris. +This is due to tripwire's extensive use of gethostbyname(), +which can only be linked dynamicaly. Please rerun configure +without the --enable-static option. +" >&2;} + +cat >>confdefs.h <<\_ACEOF +#define SOLARIS_NO_GETHOSTBYNAME 1 +_ACEOF + + fi + LIBS="-ldl $LIBS" + +for ac_header in strings.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + ;; + alpha*-*-osf*) + CXXFLAGS="${CXXFLAGS} -D_ALPHA" + ;; + *) + ;; +esac + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +return 0 + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: WARNING: + +Hmmm... doesn't look so good. I just tried linking a program +and it failed. One reason could be missing static libraries +if you are trying to compile a static binary. +" >&5 +echo "$as_me: WARNING: + +Hmmm... doesn't look so good. I just tried linking a program +and it failed. One reason could be missing static libraries +if you are trying to compile a static binary. +" >&2;} +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +# Check whether --enable-openssl was given. +if test "${enable_openssl+set}" = set; then + enableval=$enable_openssl; +fi + + +# Check whether --with-ssl-dir was given. +if test "${with_ssl_dir+set}" = set; then + withval=$with_ssl_dir; + if test "x$withval" != "xno" ; then + tryssldir=$withval + fi + + +fi + + +CORE_CRYPT_O="md5.o sha.o" +if test "x${enable_openssl}" != "xno" +then + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + if test "x$prefix" != "xNONE" ; then + tryssldir="$tryssldir $prefix" + fi + { echo "$as_me:$LINENO: checking for OpenSSL directory" >&5 +echo $ECHO_N "checking for OpenSSL directory... $ECHO_C" >&6; } +if test "${ac_cv_openssldir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for ssldir in $tryssldir "" /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/pkg /opt /opt/openssl ; do + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + LIBS="$saved_LIBS -lcrypto" + + # Skip directories if they don't exist + if test ! -z "$ssldir" -a ! -d "$ssldir" ; then + continue; + fi + if test ! -z "$ssldir" -a "x$ssldir" != "x/usr"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" + else + CPPFLAGS="-I$ssldir $saved_CPPFLAGS" + fi + fi + + # Basic test to check for compatible library and + # correct linking + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +int main(void) +{ + char a[2048]; + memset(a, 0, sizeof(a)); + RAND_add(a, sizeof(a), sizeof(a)); + return(RAND_status() <= 0); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + found_crypto=1 + break; + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + if test ! -z "$found_crypto" ; then + break; + fi + done + + if test -z "$ssldir" ; then + ssldir="(system)" + fi + + if test -z "$found_crypto" ; then + ac_cv_openssldir="not found" + else + ac_cv_openssldir=$ssldir + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_openssldir" >&5 +echo "${ECHO_T}$ac_cv_openssldir" >&6; } + +LIBS="$saved_LIBS" + +if (test ! -z "$ac_cv_openssldir" && test "x$ac_cv_openssldir" != "xnot found") ; then + ssldir=$ac_cv_openssldir + if test "x$ssldir" != "x/usr" -a "x$ssldir" != "x(system)"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" + else + CPPFLAGS="-I$ssldir $saved_CPPFLAGS" + fi + fi + LIBS="$saved_LIBS -lcrypto" + + +for ac_header in openssl/md5.h openssl/sha.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + CORE_CRYPT_O="" + fi +fi + + + +ac_config_files="$ac_config_files Makefile man/Makefile man/man4/Makefile man/man5/Makefile man/man8/Makefile src/Makefile src/cryptlib/Makefile src/core/Makefile src/db/Makefile src/fco/Makefile src/fs/Makefile src/tw/Makefile src/twcrypto/Makefile src/twparser/Makefile src/util/Makefile src/twprint/Makefile src/twadmin/Makefile src/siggen/Makefile src/tripwire/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.60. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.60, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "man/man4/Makefile") CONFIG_FILES="$CONFIG_FILES man/man4/Makefile" ;; + "man/man5/Makefile") CONFIG_FILES="$CONFIG_FILES man/man5/Makefile" ;; + "man/man8/Makefile") CONFIG_FILES="$CONFIG_FILES man/man8/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/cryptlib/Makefile") CONFIG_FILES="$CONFIG_FILES src/cryptlib/Makefile" ;; + "src/core/Makefile") CONFIG_FILES="$CONFIG_FILES src/core/Makefile" ;; + "src/db/Makefile") CONFIG_FILES="$CONFIG_FILES src/db/Makefile" ;; + "src/fco/Makefile") CONFIG_FILES="$CONFIG_FILES src/fco/Makefile" ;; + "src/fs/Makefile") CONFIG_FILES="$CONFIG_FILES src/fs/Makefile" ;; + "src/tw/Makefile") CONFIG_FILES="$CONFIG_FILES src/tw/Makefile" ;; + "src/twcrypto/Makefile") CONFIG_FILES="$CONFIG_FILES src/twcrypto/Makefile" ;; + "src/twparser/Makefile") CONFIG_FILES="$CONFIG_FILES src/twparser/Makefile" ;; + "src/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/util/Makefile" ;; + "src/twprint/Makefile") CONFIG_FILES="$CONFIG_FILES src/twprint/Makefile" ;; + "src/twadmin/Makefile") CONFIG_FILES="$CONFIG_FILES src/twadmin/Makefile" ;; + "src/siggen/Makefile") CONFIG_FILES="$CONFIG_FILES src/siggen/Makefile" ;; + "src/tripwire/Makefile") CONFIG_FILES="$CONFIG_FILES src/tripwire/Makefile" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +CYGPATH_W!$CYGPATH_W$ac_delim +PACKAGE!$PACKAGE$ac_delim +VERSION!$VERSION$ac_delim +ACLOCAL!$ACLOCAL$ac_delim +AUTOCONF!$AUTOCONF$ac_delim +AUTOMAKE!$AUTOMAKE$ac_delim +AUTOHEADER!$AUTOHEADER$ac_delim +MAKEINFO!$MAKEINFO$ac_delim +AMTAR!$AMTAR$ac_delim +install_sh!$install_sh$ac_delim +STRIP!$STRIP$ac_delim +INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim +mkdir_p!$mkdir_p$ac_delim +AWK!$AWK$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +am__leading_dot!$am__leading_dot$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +DEPDIR!$DEPDIR$ac_delim +am__include!$am__include$ac_delim +am__quote!$am__quote$ac_delim +AMDEP_TRUE!$AMDEP_TRUE$ac_delim +AMDEP_FALSE!$AMDEP_FALSE$ac_delim +AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim +CCDEPMODE!$CCDEPMODE$ac_delim +am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim +am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +CXXDEPMODE!$CXXDEPMODE$ac_delim +am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim +am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim +RANLIB!$RANLIB$ac_delim +YACC!$YACC$ac_delim +YFLAGS!$YFLAGS$ac_delim +path_to_vi!$path_to_vi$ac_delim +path_to_sendmail!$path_to_sendmail$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +EGREP!$EGREP$ac_delim +CXXCPP!$CXXCPP$ac_delim +CORE_CRYPT_O!$CORE_CRYPT_O$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 5; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| . 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir=$dirpart/$fdir + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..2622d79 --- /dev/null +++ b/configure.in @@ -0,0 +1,431 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +dnl + +AC_INIT +AC_CONFIG_SRCDIR([src/tw/tw.cpp]) +AC_CANONICAL_TARGET([]) +AM_INIT_AUTOMAKE(tripwire, 2.4.2.2) +AM_CONFIG_HEADER(config.h) + +dnl ################################# +dnl Cleanup Cruft Leftover From Patch +dnl ################################# +rm -f src/tripwire/syslog.h 2> /dev/null +chmod 755 install-sh 2> /dev/null + +dnl ############### +dnl Setup defaults +dnl ############### +CFLAGS=${CFLAGS:-"-O -pipe -Wall -Wno-non-virtual-dtor"} +CXXFLAGS=${CXXFLAGS:-"-O -pipe -Wall -Wno-non-virtual-dtor"} + +dnl ##################### +dnl Configuration options +dnl ##################### +AC_ARG_ENABLE(static, [ --enable-static compile static binaries]) +if test "x$enable_static" = xyes +then LDFLAGS="${LDFLAGS} -static" +fi +AC_ARG_ENABLE(debug, [ --enable-debug compile with debuging enabled]) +if test "x$enable_debug" = xyes +then + CFLAGS="${CFLAGS} -g" + CXXFLAGS="${CXXFLAGS} -g" + AC_DEFINE(DEBUG, 1, [Compile with debug code]) +fi + +dnl ################### +dnl Checks for programs +dnl ################### +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_PROG_YACC +AC_PATH_PROG(path_to_vi, vi) +AC_PATH_PROG(path_to_sendmail, sendmail, "", [$PATH:/usr/libexec]) + +if test "x${GXX}" != "x"; then + AC_DEFINE(HAVE_GCC, 1, [Uses the GNU gcc compiler]) +else + AC_DEFINE(HAVE_GCC, 0, [Uses the GNU gcc compiler]) +fi + +dnl ####################### +dnl Checks for header files +dnl ####################### +AC_HEADER_STDC +AC_CHECK_HEADERS(sys/param.h) +AC_CHECK_HEADERS(sys/mount.h,,, +[[#if defined(HAVE_SYS_PARAM_H) +#include +#endif +]]) +AC_CHECK_HEADERS(sys/ustat.h sys/sysmacros.h sys/syslog.h) +AC_CHECK_HEADERS(unistd.h syslog.h iconv.h langinfo.h sys/statfs.h) +AC_CHECK_HEADERS(signum.h bits/signum.h, break ) +AC_CHECK_HEADERS(stdarg.h varargs.h, break ) + +dnl # Special case for malloc.h, because it's depreciated on most systems. +CPPFLAGS_SAVE="${CPPFLAGS}" +CPPFLAGS="${CPPFLAGS} -Werror" +AC_CHECK_HEADERS(malloc.h) +CPPFLAGS="${CPPFLAGS_SAVE}" + +dnl ############################################################# +dnl Checks for typedefs, structures, and compiler characteristics +dnl ############################################################# +AC_C_CONST +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_C_BIGENDIAN +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long long) + +dnl All platforms we support use 2's complement, are byte aligned, etc... +AC_DEFINE(USES_1S_COMPLEMENT, 0, [Uses one's complement]) +AC_DEFINE(USES_2S_COMPLEMENT, 1, [Uses two's complement]) +AC_DEFINE(USES_SIGNED_MAGNITUDE, 0, [Uses signed magnitute]) +AC_DEFINE(IS_BYTE_ALIGNED, 1, [Is byte aligned]) +AC_DEFINE(EXCEPTION_NAMESPACE, std::, [this is the prefix for STL exception functions]) + +dnl We used to check for UNIX or Unix-like target platforms, +dnl but that is a little extreme, so just assume that the +dnl target is unix. This can still be changed in config.h +AC_DEFINE(IS_UNIX, 1, [Is a unix type platform]) + +dnl whether or not to generate debuging code? +AC_DEFINE(NDEBUG, 1, [don't generate debuging code]) + +dnl ############################# +dnl Checks for standard functions +dnl ############################# +AC_CHECK_FUNCS(strftime gethostname gethostid) +AC_CHECK_FUNCS(mkstemp mktemp, break) + +dnl ############################################## +dnl Checks for various platform specific libraries +dnl ############################################## + +dnl socket? Solaris has it somewhere else. +AC_CHECK_LIB(c, socket, [:], [ + AC_CHECK_LIB(socket, socket, [ + LIBS="-lsocket $LIBS" + ], [:]) ]) + +dnl gethostbyname? Solaris has it somewhere else. +AC_CHECK_LIB(c, gethostbyname, [:], [ + AC_CHECK_LIB(nsl, gethostbyname, [ + LIBS="-lnsl $LIBS" + ], [:]) ]) + +dnl check for stl library +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +dnl +dnl Check for STL headers +dnl +AC_CHECK_HEADER(locale,, [ + dnl Don't have native STL headers, look in other places + AC_CACHE_CHECK([for STLport directory], ac_cv_stlportdir, [ + found_locale="" + for inclpath in /usr/local/include /usr/local/include/stlport + do + CPPFLAGS_save=${CPPFLAGS} + CPPFLAGS="${CPPFLAGS} -I${inclpath}" + AC_TRY_COMPILE([ +#include +] + , , [ found_locale="1" ], ) + CPPFLAGS=${CPPFLAGS_save} + if test "x${found_locale}" = "x1" + then + ac_cv_stlportdir=${inclpath} + break + fi + done + if test "x${found_locale}" = "x"; then + echo "not found" + AC_MSG_WARN( [ + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + ]) + fi + ]) + ]) + if test "x${ac_cv_stlportdir}" != "x" + then + CPPFLAGS="${CPPFLAGS} -I${ac_cv_stlportdir}" + fi + AC_TRY_LINK([#include ],,,[ + dnl Don't have native STL library, look in other places + dnl First check for POSIX threads if we compile STLport, because it needs it + AC_CHECK_FUNC(pthread_getspecific, [:], [ + + LDFLAGS_TEMP="${LDFLAGS}" + LDFLAGS="${LDFLAGS_TEMP} -pthread" + unset ac_cv_func_pthread_getspecific + AC_CHECK_FUNC(pthread_getspecific, [:], [ + + LDFLAGS="${LDFLAGS_TEMP} -lpthread" + unset ac_cv_func_pthread_getspecific + AC_CHECK_FUNC(pthread_getspecific, [:], [ + LDFLAGS="${LDFLAGS_TEMP}" + AC_MSG_ERROR([No posix threads detected, cannot continue.]) ]) + ]) + ]) + + AC_CACHE_CHECK([for STLport library directory], ac_cv_stlportlib, [ + found_lib="" + for inclpath in /usr/local/lib /usr/local/lib/stlport + do + for stllib in stlport stlport_gcc + do + LDFLAGS_save=${LDFLAGS} + LIBS_save=${LIBS} + LDFLAGS="${LDFLAGS} -L${inclpath}" + LIBS="${LIBS} -l${stllib}" + AC_TRY_LINK([ +#include +] + , , [ found_lib="1" ], ) + LDFLAGS=${LDFLAGS_save} + LIBS=${LIBS_save} + if test "x${found_lib}" = "x1" + then + ac_cv_stlportlib=${inclpath} + break + fi + done + if test "x${found_lib}" = "x1" + then + break + fi + done + if test "x${found_lib}" = "x"; then + echo "not found" + AC_MSG_WARN( [ + + *** You don't seem to have STL support in your C++ compiler. + *** You can try to build tripwire, but it probably won't compile. + ]) + fi + ]) + if test "x${ac_cv_stlportdir}" != "x" + then + LDFLAGS="${LDFLAGS} -L${ac_cv_stlportlib}" + LIBS="${LIBS} -l${stllib}" + fi + ]) +AC_LANG_RESTORE + +dnl ##################### +dnl STL specific headers +dnl ##################### +AC_CHECK_HEADERS(wchar.h) + +dnl ####################################################################### +dnl Local checks/hacks. The goal is to make this part as short as possible +dnl ####################################################################### +AC_DEFINE_UNQUOTED(TARGET_OS, "${target}", [Target OS]) +case $target in + i386-*-freebsd*) + ;; + alpha-*-freebsd*) + ;; + i386-*-openbsd*) + ;; + *-*-netbsd*) + ;; + i[[0-9]]86-pc-linux*) + ;; + sparc-*-linux*) + ;; + *-sun-solaris*) + if test "x$enable_static" = xyes + then + AC_MSG_WARN( [ + +Sorry, tripwire will not properly link staticaly under Solaris. +This is due to tripwire's extensive use of gethostbyname(), +which can only be linked dynamicaly. Please rerun configure +without the --enable-static option. +]) + AC_DEFINE(SOLARIS_NO_GETHOSTBYNAME, 1, [Don't use gethostbyname() on Solaris]) + fi + LIBS="-ldl $LIBS" + AC_CHECK_HEADERS(strings.h) + ;; + alpha*-*-osf*) + CXXFLAGS="${CXXFLAGS} -D_ALPHA" + ;; + *) + ;; +esac + +dnl ################################################### +dnl Try linking a simple program with the flags we have +dnl ################################################### +AC_TRY_LINK( , return 0 , , [ AC_MSG_WARN( [ + +Hmmm... doesn't look so good. I just tried linking a program +and it failed. One reason could be missing static libraries +if you are trying to compile a static binary. +]) ] ) + +dnl Check for OpenSSL, now that we have a working compiler +AC_ARG_ENABLE(openssl, + [ --disable-openssl don't link against OpenSSL libraries]) +AC_ARG_WITH(ssl-dir, + [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], + [ + if test "x$withval" != "xno" ; then + tryssldir=$withval + fi + ] +) + +dnl ################# +dnl Check for OpenSSL +dnl ################# +CORE_CRYPT_O="md5.o sha.o" +if test "x${enable_openssl}" != "xno" +then + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + if test "x$prefix" != "xNONE" ; then + tryssldir="$tryssldir $prefix" + fi + AC_CACHE_CHECK([for OpenSSL directory], ac_cv_openssldir, [ + for ssldir in $tryssldir "" /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/pkg /opt /opt/openssl ; do + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + LIBS="$saved_LIBS -lcrypto" + + # Skip directories if they don't exist + if test ! -z "$ssldir" -a ! -d "$ssldir" ; then + continue; + fi + if test ! -z "$ssldir" -a "x$ssldir" != "x/usr"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" + else + CPPFLAGS="-I$ssldir $saved_CPPFLAGS" + fi + fi + + # Basic test to check for compatible library and + # correct linking + AC_TRY_RUN( + [ +#include +#include +int main(void) +{ + char a[2048]; + memset(a, 0, sizeof(a)); + RAND_add(a, sizeof(a), sizeof(a)); + return(RAND_status() <= 0); +} + ], + [ + found_crypto=1 + break; + ], [] + ) + + if test ! -z "$found_crypto" ; then + break; + fi + done + + if test -z "$ssldir" ; then + ssldir="(system)" + fi + + if test -z "$found_crypto" ; then + ac_cv_openssldir="not found" + else + ac_cv_openssldir=$ssldir + fi +]) + +LIBS="$saved_LIBS" + +if (test ! -z "$ac_cv_openssldir" && test "x$ac_cv_openssldir" != "xnot found") ; then + dnl Need to recover ssldir - test above runs in subshell + ssldir=$ac_cv_openssldir + if test "x$ssldir" != "x/usr" -a "x$ssldir" != "x(system)"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" + else + CPPFLAGS="-I$ssldir $saved_CPPFLAGS" + fi + fi + LIBS="$saved_LIBS -lcrypto" + AC_CHECK_HEADERS(openssl/md5.h openssl/sha.h) + CORE_CRYPT_O="" + fi +fi + +dnl ##################################### +dnl Export the variables we use +dnl ##################################### +AC_SUBST(CORE_CRYPT_O) + +AC_CONFIG_FILES([ +Makefile +man/Makefile +man/man4/Makefile +man/man5/Makefile +man/man8/Makefile +src/Makefile +src/cryptlib/Makefile +src/core/Makefile +src/db/Makefile +src/fco/Makefile +src/fs/Makefile +src/tw/Makefile +src/twcrypto/Makefile +src/twparser/Makefile +src/util/Makefile +src/twprint/Makefile +src/twadmin/Makefile +src/siggen/Makefile +src/tripwire/Makefile +]) +AC_OUTPUT diff --git a/contrib/make-bin-dist b/contrib/make-bin-dist new file mode 100755 index 0000000..10995e6 --- /dev/null +++ b/contrib/make-bin-dist @@ -0,0 +1,21 @@ +#!/bin/sh +# +# A very cheesy script to prep a release +# + +PRODUCT=tripwire +VERSION=2.4.2.2 +ARCH=x86 +TYPE=bin +ROOT_DIR=$PRODUCT-$VERSION-$ARCH-$TYPE +EXCLUDES=.svn + +mkdir $ROOT_DIR +ln -s ../bin ../contrib ../man ../policy $ROOT_DIR/ +ln -s ../COPYING ../ChangeLog ../INSTALL ../MAINTAINERS $ROOT_DIR/ +ln -s ../TRADEMARK ../COMMERCIAL ../install ../install-sh $ROOT_DIR/ + +tar jhcf $ROOT_DIR.tar.bz2 $ROOT_DIR --exclude $EXCLUDES + +sha1sum $ROOT_DIR.tar.bz2 > $ROOT_DIR.sha1 +sha1sum bin/* >> $ROOT_DIR.sha1 diff --git a/contrib/tripwire-check b/contrib/tripwire-check new file mode 100755 index 0000000..74758f6 --- /dev/null +++ b/contrib/tripwire-check @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Tripwire cron script borrowed from Linux and modified for generic situations. +# You should of course change path names to suit your environment. +# +# Contributed by Timothy K Ewing +# +HOST_NAME=`uname -n` +TWCFG_PATH=/usr/local/etc +TWDB_PATH=/usr/local/lib/tripwire +TWROOT_PATH=/usr/local/sbin +MAILTO="root" # Email addresses that should recieve reports + +# +# Define checks which alert user to misconfiguration or run the check +# +if [ ! -e ${TWDB_PATH}/${HOST_NAME}.twd ]; then + echo "**** Error: Tripwire database for ${HOST_NAME} not found. ****" + echo "**** Verify tripwire was installed and/or "tripwire --init". ****" +else + test -f ${TWCFG_PATH}/tw.cfg && ${TWROOT_PATH}/tripwire --check | \ + mail -s "${HOST_NAME} tripwire-check" ${MAILTO} +fi diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/install/install.cfg b/install/install.cfg new file mode 100644 index 0000000..0c6b3f7 --- /dev/null +++ b/install/install.cfg @@ -0,0 +1,109 @@ +# +# install.cfg +# +# default install.cfg for: +# Tripwire(R) 2.4 Open Source +# +# NOTE: This is a Bourne shell script that stores installation +# parameters for your installation. The installer will +# execute this file to generate your config file and also to +# locate any special configuration needs for your install. +# Protect this file, because it is possible for +# malicious code to be inserted here +# +# This version of Tripwire has been modified to conform to the FHS +# standard for Unix-like operating systems. +# +# To change the install directory for any tripwire files, modify +# the paths below as necessary. +# +#======================================================= + +# If CLOBBER is true, then existing files are overwritten. +# If CLOBBER is false, existing files are not overwritten. +CLOBBER=false + +# Tripwire binaries are stored in TWBIN. +TWBIN="${prefix}/sbin" + +# Tripwire policy files are stored in TWPOLICY. +TWPOLICY="${sysconfdir}" + +# Tripwire manual pages are stored in TWMAN. +TWMAN="${prefix}/man" + +# Tripwire database files are stored in TWDB. +TWDB="${prefix}/lib/tripwire" + +# Tripwire documents directory +TWDOCS="${prefix}/doc/tripwire" + +# The Tripwire site key files are stored in TWSITEKEYDIR. +TWSITEKEYDIR="${TWPOLICY}" + +# The Tripwire local key files are stored in TWLOCALKEYDIR. +TWLOCALKEYDIR="${TWPOLICY}" + +# Tripwire report files are stored in TWREPORT. +TWREPORT="${TWDB}/report" + +# This sets the default text editor for Tripwire. +TWEDITOR="${path_to_vi}" + +# TWLATEPROMTING controls the point when tripwire asks for a password. +TWLATEPROMPTING=false + +# TWLOOSEDIRCHK selects whether the directory should be monitored for +# properties that change when files in the directory are monitored. +TWLOOSEDIRCHK=false + +# TWMAILNOVIOLATIONS determines whether Tripwire sends a no violation +# report when integrity check is run with --email-report but no rule +# violations are found. This lets the admin know that the integrity +# was run, as opposed to having failed for some reason. +TWMAILNOVIOLATIONS=true + +# TWEMAILREPORTLEVEL determines the verbosity of e-mail reports. +TWEMAILREPORTLEVEL=3 + +# TWREPORTLEVEL determines the verbosity of report printouts. +TWREPORTLEVEL=3 + +# TWSYSLOG determines whether Tripwire will log events to the system log +TWSYSLOG=false + +##################################### +# Mail Options - Choose the appropriate +# method and comment the other section +##################################### + +##################################### +# SENDMAIL options - DEFAULT +# +# Either SENDMAIL or SMTP can be used to send reports via TWMAILMETHOD. +# Specifies which sendmail program to use. +##################################### + +TWMAILMETHOD=SENDMAIL + +##################################### +# SMTP options +# +# TWSMTPHOST selects the SMTP host to be used to send reports. +# SMTPPORT selects the SMTP port for the SMTP mail program to use. +##################################### + +#TWMAILMETHOD=SMTP +#TWSMTPHOST="mail.domain.com" +#TWSMTPPORT=25 + +# If sendmail wasn't found in the path, set then clear out +# TWMAILPROGRAM so the install.sh does the right thing and +# tells the user about the missing configuration +# +path_to_sendmail=/usr/sbin/sendmail +if [ -z "$path_to_sendmail" ] ; then + TWMAILPROGRAM="" +else + TWMAILPROGRAM="${path_to_sendmail} -oi -t" +fi diff --git a/install/install.sh b/install/install.sh new file mode 100755 index 0000000..60962ca --- /dev/null +++ b/install/install.sh @@ -0,0 +1,922 @@ +#!/bin/sh + +######################################################### +######################################################### +## +## Tripwire(R) 2.4 Open Source install script +## +######################################################### +######################################################### + +##======================================================= +## Setup +##======================================================= + +##------------------------------------------------------- +## Sanity checks, mostly stolen (with permission) +## from Larry Wall's metaconfig. +##------------------------------------------------------- + +PATH='.:/bin:/usr/bin' +export PATH || (echo 'You must use sh to run this script'; kill $$) +if [ ! -t 0 ] ; then + echo "Say 'sh install.sh', not 'sh < install.sh'" + exit 1 +fi + +##------------------------------------------------------- +## The usage message. +##------------------------------------------------------- + +USAGE="install.sh [] [-n] [-f] [-s ] [-l ]" + +##------------------------------------------------------- +## Figure out how to do an echo without newline. +##------------------------------------------------------- + +if [ "`echo -n`" = "-n" ] ; then + n="" + c="\c" +else + n=" -n" + c="" +fi + +##------------------------------------------------------- +## Better have a copy of tar! +## If /bin/sh does not exist or is not readable (seems +## fairly unlikely), then this will fail. +##------------------------------------------------------- + +(tar cvf /dev/null /bin/sh) 2> /dev/null 1>&2 +if [ $? -ne 0 ]; then + echo "tar command not found -- aborting install." + exit 1 +fi + +##------------------------------------------------------- +## Can't live without sed. +##------------------------------------------------------- + +(echo 'abc' | sed 's/abc/def/') 2> /dev/null 1>&2 +if [ $? -ne 0 ]; then + echo "sed command not found -- aborting install." + exit 1 +fi + +##------------------------------------------------------- +## Does this system have a copy of awk we can use? +##------------------------------------------------------- + +AWK="" +awknames="awk nawk gawk" +for p in $awknames; do + ($p '{ exit 0 }' < /dev/null) 2> /dev/null 1>&2 + if [ $? -eq 0 ]; then + AWK=$p + break + fi +done + +##------------------------------------------------------- +## Does this system have a copy of grep we can use? +## Some greps don't return status (amazing, huh?), +## so we look for a copy of grep that +## returns 0 status for an exact match +## returns 0 status for a case-insensitive match +## returns 0 status for a wildcard match +## returns non-zero status for a failed match +##------------------------------------------------------- + +GREP="" +grepnames="grep egrep" +lcgrepstr="findensiemich" # all lower case +mcgrepstr="FindenSieMich" # mixed case +wcgrepstr="sie.ich$" # wild card match +nogrepstr="WoBistDu" # should not be able to find this +for p in $grepnames; do + (echo "$lcgrepstr" | $p "$lcgrepstr") 2> /dev/null 1>&2 + if [ $? -eq 0 ]; then + (echo "$lcgrepstr" | $p -i "$mcgrepstr") 2> /dev/null 1>&2 + if [ $? -eq 0 ]; then + (echo "$lcgrepstr" | $p "$wcgrepstr") 2> /dev/null 1>&2 + if [ $? -eq 0 ]; then + (echo "$lcgrepstr" | $p "$nogrepstr") 2> /dev/null 1>&2 + if [ $? -ne 0 ]; then + GREP=$p + break + fi + fi + fi + fi +done + +##------------------------------------------------------- +## Does this system have a pager that we can use? +## Use cat if desperate. +##------------------------------------------------------- + +MORE="cat" +morenames="more less cat" +for p in $morenames; do + ($p $0 < /dev/null) 2> /dev/null 1>&2 + if [ $? -eq 0 ]; then + MORE=$p + break + fi +done + +##------------------------------------------------------- +## Does this system have a copy of uname we can use? +##------------------------------------------------------- + +UNAME="" +(uname -s -r -v) 2> /dev/null 1>&2 +if [ $? -eq 0 ]; then + UNAME=uname +fi + +##======================================================= +## Command line +##======================================================= + +##------------------------------------------------------- +## Miscellaneous configuration parameters. +##------------------------------------------------------- + +# prefix +prefix="${prefix:=/usr}" + +# License File name +TWLICENSEFILE="COPYING" + +# Default Tripwire configuration file. +TW_CONFIG_FILE="tw.cfg" + +# Name of initial cleartext Tripwire config file. +CLR_CONFIG_FILE="twcfg.txt" + +# Name of initial cleartext Tripwire policy file. +CLR_POLICY_FILE="twpol.txt" + +# Default installation script configuration file. +INSTALL_CONFIG_FILE="./install/install.cfg" + +# Relative path to dir that contains the pkg files. +PKG_DIR="pkg" + +# Names of the package files. +# See also copy-files section below. +BIN_PKG="bin.pkg" +POL_PKG="policy.pkg" +MAN_PKG="man.pkg" + +# Starting directory. +START_DIR=`pwd` + +# Site passphrase. +TW_SITE_PASS="" + +# Local passphrase. +TW_LOCAL_PASS="" + +# If clobber==true, overwrite files; if false, do not overwrite files. +CLOBBER="false" + +# If prompt==true, ask for confirmation before continuing with install. +PROMPT="true" + +# Guess where the toplevel for the distribution is. +# A bad guess is the current directory +TAR_DIR=${TAR_DIR:-${START_DIR}} + +OS=`uname -s` +POLICYSRC="twpol-${OS:=GENERIC}.txt" +if [ ! -r ${TAR_DIR}/policy/${POLICYSRC} ] +then POLICYSRC="twpol-GENERIC.txt" +fi + +##------------------------------------------------------- +## Parse the command line. +##------------------------------------------------------- + +while [ "x$1" != "x" ] ; do + case "$1" in + -n) PROMPT="false"; xCLOBBER="true" ;; + -f) xCLOBBER="true" ;; + -s) case "$2" in + "" | -*) + echo "Error: missing sitepassphrase with -s option." 1>&2 + echo "$USAGE" + exit 1 ;; + *) TW_SITE_PASS="$2"; shift ;; + esac ;; + -l) case "$2" in + "" | -*) + echo "Error: missing localpassphrase with -l option." 1>&2 + echo "$USAGE" + exit 1 ;; + *) TW_LOCAL_PASS="$2"; shift ;; + esac ;; + -*) echo "Error: unknown argument $1" 1>&2 + echo "$USAGE" + exit 1 ;; + *) INSTALL_CONFIG_FILE="$1" + if [ $xgot ] ; then + echo "Error: incorrect number of arguments" 1>&2 + echo "$USAGE" + exit 1 + fi + xgot="true" + ;; + esac + shift +done + +##------------------------------------------------------- +## Print the sign-on banner here before the first +## non-error message is displayed. +##------------------------------------------------------- + +cat << END_OF_TEXT + +Installer program for: +Tripwire(R) 2.4 Open Source + +Copyright (C) 1998-2000 Tripwire (R) Security Systems, Inc. Tripwire (R) +is a registered trademark of the Purdue Research Foundation and is +licensed exclusively to Tripwire (R) Security Systems, Inc. + +END_OF_TEXT + + +##------------------------------------------------------- +## Print a message if the user aborts the install. +##------------------------------------------------------- + +trap "echo ; echo 'Installation has been halted.' ; exit 1" 1 2 15 + +##------------------------------------------------------- +## The pathname variables we expect to find in the +## install.cfg file. +##------------------------------------------------------- + +paths="TWBIN TWMAN TWPOLICY TWREPORT TWDB TWSITEKEYDIR TWLOCALKEYDIR" +path2="TWBIN TWPOLICY TWREPORT TWDB TWSITEKEYDIR TWLOCALKEYDIR" +path3="TWMAN TWDOCS" + +##======================================================= +## User License Agreement +##======================================================= + +##------------------------------------------------------- +## Where is the license agreement file? +##------------------------------------------------------- +EULA_PATH="$TWLICENSEFILE" + +##------------------------------------------------------- +## If prompting is turned on, get acceptance from user before moving on. +##------------------------------------------------------- + +if [ "$PROMPT" = "true" ] ; then + echo + echo "LICENSE AGREEMENT for Tripwire(R) 2.4 Open Source" + echo + echo "Please read the following license agreement. You must accept the" + echo "agreement to continue installing Tripwire." + echo + echo "Press ENTER to view the License Agreement." + echo + read inputstring + + # Show the user the license: + ${PAGER:-${MORE}} $EULA_PATH + + # Now confirm that the user agrees to the license: + echo + echo 'Please type "accept" to indicate your acceptance of this' + (echo $n "license agreement. [do not accept] " $c) 1>&2 + read ans + case "$ans" in + accept|Accept|ACCEPT) ;; + *) echo "YOU DID NOT ACCEPT THE LICENSE AGREEMENT. INSTALLATION TERMINATED." + exit 1 + ;; + esac +fi + +##------------------------------------------------------- +## Execute the installation configuration file +##------------------------------------------------------- + +echo "Using configuration file $INSTALL_CONFIG_FILE" +echo +. $INSTALL_CONFIG_FILE + +##======================================================= +## Process the configuration parameters. +##======================================================= + +##------------------------------------------------------- +## Value on command line, if present, overrides value in +## config file. Value must either be "true" or "false" +## exactly; if it's not the former, make it the latter. +##------------------------------------------------------- + +CLOBBER=${xCLOBBER-$CLOBBER} +if [ ! "$CLOBBER" = "true" ] ; then + CLOBBER="false" +fi + +##------------------------------------------------------- +## If no prompting was selected, both site and local +## passphrases must be specified on the command line. +##------------------------------------------------------- + +if [ "$PROMPT" = "false" ] ; then + if [ -z "$TW_SITE_PASS" ] || [ -z "$TW_LOCAL_PASS" ] ; then + echo "Error: You must specify site and local passphrase" 1>&2 + echo "if no prompting is chosen." 1>&2 + echo "$USAGE" + exit 1 + fi +fi + +##------------------------------------------------------- +## For each pathname variable: +## Make sure it's defined. +## Strip trailing slashes from each of the directory variables. +## Determine length of longest parameter name. +##------------------------------------------------------- + +len=0 +for i in $paths; do + +# Is it defined? + eval "test \"\$${i}\"" + if [ $? -ne 0 ] ; then + echo "Error: configuration parameter \$$i undefined." 1>&2 + echo "There is an error in the configuration file ${INSTALL_CONFIG_FILE}." 1>&2 + exit 1 + fi + +# Strip trailing slashes. +# Squash multiple internal slashes down to one. + eval "xtmp=\$${i}" + xtmp=`echo $xtmp | sed 's/\/*$//'` + xtmp=`echo $xtmp | sed 's/\/\/*/\//g'` + eval "${i}=\"$xtmp\"" + +# Does it start with a slash (i.e. is it an absolute pathname)? + ytmp=`echo $xtmp | sed 's/^\///'` + if [ "$xtmp" = "$ytmp" ] ; then + echo "Error: \$$i is not an absolute pathname." 1>&2 + echo 'Relative pathnames may not be used.' 1>&2 + exit 1 + fi + +# What is the length of the longest variable name? + if [ "$AWK" != "" ] ; then + xlen=`echo "${i}" | $AWK '{ print length }'` + if [ $xlen -gt $len ] ; then + len=$xlen + fi + fi +done + +##------------------------------------------------------- +## Check Mailmethod for SMTP. If SMTP ignore MAILPROGRAM. +## If SENDMAIL is specified, verify that the specified +## mail program exists +##------------------------------------------------------- +echo "Checking for programs specified in install configuration file...." +echo + +TWMAILMETHOD=${TWMAILMETHOD:-'SENDMAIL'} +if [ "$TWMAILMETHOD" = "SENDMAIL" ] ; then + + if [ -n "$TWMAILPROGRAM" ] ; then + echo "${TWMAILPROGRAM} exists. Continuing installation." + echo + else + echo "" + echo "*** No sendmail found. Edit install.cfg and set" + echo "*** TWMAILPROGRAM to full path to sendmail, or" + echo "*** change TWMAILMETHOD to SMTP and set SMTP" + echo "*** settings appropriately." + echo "" + exit 1 + fi +else + echo "Using SMTP mail protocol." + echo "MAILPROGRAM variable will be ignored." + echo "Continuing installation." + echo + fi + +##------------------------------------------------------- +## Verify that the specified editor program exists +##------------------------------------------------------- + +TWEDITOR=${TWEDITOR:-'/bin/vi'} + +if [ -x ${TWEDITOR} ]; then + echo "${TWEDITOR} exists. Continuing installation." + echo +else + echo "${TWEDITOR} does not exist. Exiting." + exit 1 +fi + +##------------------------------------------------------- +## Where are the bin files? Did they build okay? Don't +## bother to install if they don't exist. +##------------------------------------------------------- + +echo +echo "----------------------------------------------" +echo "Verifying existence of binaries..." +echo + +BASE_DIR="./" +if [ ! -z "$BASE_DIR" ] ; then + BIN_DIR="${BASE_DIR}bin" +fi + +CWD=`pwd` +cd "$TAR_DIR" +TAR_DIR=`pwd` +cd "$BASE_DIR" +files="$BIN_DIR/siggen $BIN_DIR/tripwire $BIN_DIR/twprint $BIN_DIR/twadmin" +for i in $files; do + if [ -s "$i" ] ; then + echo "$i found" + else + echo "$i missing. Build did not complete successfully." + exit 1 + fi +done +cd "$CWD" + +##------------------------------------------------------- +## Print the list of target directories. +##------------------------------------------------------- + +echo +echo "This program will copy Tripwire files to the following directories:" +echo + +for i in $paths; do + if [ "$AWK" != "" ] ; then + eval "echo \"${i}\" | $AWK '{printf \"%${len}s: \", \$1}'" + eval "echo \"\$${i}\"" + else + eval "echo \"\$${i}\"" + fi +done + +##------------------------------------------------------- +## Display value of clobber. +##------------------------------------------------------- + +echo +echo "CLOBBER is $CLOBBER." + +##------------------------------------------------------- +## Prompt to continue. +##------------------------------------------------------- + +if [ "$PROMPT" = "true" ] ; then + echo + (echo $n "Continue with installation? [y/n] " $c) 1>&2 + read ans + case "$ans" in + [yY]*) ;; + *) echo "Installation has been halted." + exit 1; + ;; + esac +fi + +##======================================================= +## Create directories. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Creating directories..." +echo + +##------------------------------------------------------- +## Create only directories that do not already exist. +## Change permissions only on directories we create. +## Exit if mkdir fails. +##------------------------------------------------------- + +for i in $path2; do + eval "d=\$${i}" + if [ ! -d "$d" ] ; then + mkdir -p "$d" + if [ ! -d "$d" ] ; then + echo "Error: unable to create directory $d" + exit 1 + else + echo "$d: created" + chmod 0750 "$d" > /dev/null + fi + else + echo "$d: already exists" + fi +done + +for i in $path3; do + eval "d=\$${i}" + if [ ! -d "$d" ] ; then + mkdir -p "$d" + if [ ! -d "$d" ] ; then + echo "Error: unable to create directory $d" + exit 1 + else + echo "$d: created" + chmod 0755 "$d" > /dev/null + fi + else + echo "$d: already exists" + fi +done + + +##======================================================= +## Copy all files to the location specified. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Copying files..." +echo + +##------------------------------------------------------- +## Find all the relevant files. For each +## file in the list, if it exists with size greater +## than zero AND (clobber == false), then don't +## overwrite that file. +## Associate loose file names with directories. +## Special case the Release_Notes file through README_LOC. +## This is used in the install script's closing message. +## Make sure README_LOC and fil1 stay in sync. +##------------------------------------------------------- + +#f1=' ff=$README ; d="" ; dd=$TWDOCS ; rr=0444 ' +#f2=' ff=$REL_NOTES ; d="" ; dd=$TWDOCS ; rr=0444 ' +f3=' ff=$TWLICENSEFILE ; d="" ; dd=$TWDOCS ; rr=0444 ' +#f4=' ff=tripwire ; d="/bin" ; dd=$TWBIN ; rr=0550 ' +#f5=' ff=twadmin ; d="/bin" ; dd=$TWBIN ; rr=0550 ' +#f6=' ff=twprint ; d="/bin" ; dd=$TWBIN ; rr=0550 ' +#f7=' ff=siggen ; d="/bin" ; dd=$TWBIN ; rr=0550 ' +f8=' ff=TRADEMARK ; d="" ; dd=$TWDOCS ; rr=0444 ' +f9=' ff=policyguide.txt ; d="/policy" ; dd=$TWDOCS ; rr=0444 ' +f10=' ff=${POLICYSRC} ; d="/policy" ; dd=$TWPOLICY ; rr=0640 ' +#f11=' ff=twpolicy.4 ; d="/man/man4" ; dd=$TWMAN/man4 ; rr=0444 ' +#f12=' ff=twconfig.4 ; d="/man/man4" ; dd=$TWMAN/man4 ; rr=0444 ' +#f13=' ff=twfiles.5 ; d="/man/man5" ; dd=$TWMAN/man5 ; rr=0444 ' +#f14=' ff=siggen.8 ; d="/man/man8" ; dd=$TWMAN/man8 ; rr=0444 ' +#f15=' ff=tripwire.8 ; d="/man/man8" ; dd=$TWMAN/man8 ; rr=0444 ' +#f16=' ff=twadmin.8 ; d="/man/man8" ; dd=$TWMAN/man8 ; rr=0444 ' +#f17=' ff=twintro.8 ; d="/man/man8" ; dd=$TWMAN/man8 ; rr=0444 ' +#f18=' ff=twprint.8 ; d="/man/man8" ; dd=$TWMAN/man8 ; rr=0444 ' + +# Binaries and manpages are already installed by the install target +loosefiles="f3 f8 f9 f10" + +for i in $loosefiles; do + eval "eval \"\$$i\"" + f=${TAR_DIR}$d/$ff + ff=${dd}/$ff + if [ -s $ff ] && [ "$CLOBBER" = "false" ] ; then + echo "$ff: file already exists" + else + cp "$f" "$dd" + if [ $? -eq 0 ]; then + echo "$ff: copied" + chmod "$rr" "$ff" > /dev/null + else + echo "$ff: copy failed" + fi + fi +done + +##======================================================= +## Files are now present on user's system. +## Begin Tripwire configuration. +##======================================================= + +##------------------------------------------------------- +## Set default values for Tripwire file names. +##------------------------------------------------------- + +HOST_NAME=`uname -n 2>/dev/null` + +LOCAL_KEY="${TWLOCALKEYDIR}/${HOST_NAME:=localhost}-local.key" +SITE_KEY="${TWSITEKEYDIR}/site.key" +CONFIG_FILE="${TWPOLICY}/$TW_CONFIG_FILE" # Signed config file +POLICY_FILE="${TWPOLICY}/tw.pol" # Signed policy file +TXT_CFG="${TWPOLICY}/${CLR_CONFIG_FILE}" # Cleartext config file +TXT_POL="${TWPOLICY}/$CLR_POLICY_FILE" # Cleartext policy file +TWADMIN="${TWBIN}/twadmin" + +##------------------------------------------------------- +## If user has to enter a passphrase, give some +## advice about what is appropriate. +##------------------------------------------------------- + +if [ -z "$TW_SITE_PASS" ] || [ -z "$TW_LOCAL_PASS" ]; then +cat << END_OF_TEXT + +---------------------------------------------- +The Tripwire site and local passphrases are used to +sign a variety of files, such as the configuration, +policy, and database files. + +Passphrases should be at least 8 characters in length +and contain both letters and numbers. + +See the Tripwire manual for more information. +END_OF_TEXT +fi + +##======================================================= +## Generate keys. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Creating key files..." + +##------------------------------------------------------- +## Site key file. +##------------------------------------------------------- + +# If clobber is true, and prompting is off (unattended operation) +# and the key file already exists, remove it. Otherwise twadmin +# will prompt with an "are you sure?" message. + +if [ "$CLOBBER" = "true" ] && [ "$PROMPT" = "false" ] && [ -f "$SITE_KEY" ] ; then + rm -f "$SITE_KEY" +fi + +if [ -f "$SITE_KEY" ] && [ "$CLOBBER" = "false" ] ; then + echo "The site key file \"$SITE_KEY\"" + echo 'exists and will not be overwritten.' +else + cmdargs="--generate-keys --site-keyfile \"$SITE_KEY\"" + if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" + fi + eval "\"$TWADMIN\" $cmdargs" + if [ $? -ne 0 ] ; then + echo "Error: site key generation failed" + exit 1 + else chmod 640 "$SITE_KEY" + fi +fi + +##------------------------------------------------------- +## Local key file. +##------------------------------------------------------- + +# If clobber is true, and prompting is off (unattended operation) +# and the key file already exists, remove it. Otherwise twadmin +# will prompt with an "are you sure?" message. + +if [ "$CLOBBER" = "true" ] && [ "$PROMPT" = "false" ] && [ -f "$LOCAL_KEY" ] ; then + rm -f "$LOCAL_KEY" +fi + +if [ -f "$LOCAL_KEY" ] && [ "$CLOBBER" = "false" ] ; then + echo "The site key file \"$LOCAL_KEY\"" + echo 'exists and will not be overwritten.' +else + cmdargs="--generate-keys --local-keyfile \"$LOCAL_KEY\"" + if [ -n "$TW_LOCAL_PASS" ] ; then + cmdargs="$cmdargs --local-passphrase \"$TW_LOCAL_PASS\"" + fi + eval "\"$TWADMIN\" $cmdargs" + if [ $? -ne 0 ] ; then + echo "Error: local key generation failed" + exit 1 + else chmod 640 "$LOCAL_KEY" + fi +fi + +##======================================================= +## Generate tripwire configuration file. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Generating Tripwire configuration file..." + +cat << END_OF_TEXT > "$TXT_CFG" +ROOT =$TWBIN +POLFILE =$POLICY_FILE +DBFILE =$TWDB/\$(HOSTNAME).twd +REPORTFILE =$TWREPORT/\$(HOSTNAME)-\$(DATE).twr +SITEKEYFILE =$SITE_KEY +LOCALKEYFILE =$LOCAL_KEY +EDITOR =$TWEDITOR +LATEPROMPTING =${TWLATEPROMPTING:-false} +LOOSEDIRECTORYCHECKING =${TWLOOSEDIRCHK:-false} +MAILNOVIOLATIONS =${TWMAILNOVIOLATIONS:-true} +EMAILREPORTLEVEL =${TWEMAILREPORTLEVEL:-3} +REPORTLEVEL =${TWREPORTLEVEL:-3} +MAILMETHOD =${TWMAILMETHOD:-SENDMAIL} +SYSLOGREPORTING =${TWSYSLOG:=true} +END_OF_TEXT + +if [ "$TWMAILMETHOD" = "SMTP" ] ; then +cat << SMTP_TEXT >> "$TXT_CFG" +SMTPHOST =${TWSMTPHOST:-mail.domain.com} +SMTPPORT =${TWSMTPPORT:-"25"} +SMTP_TEXT +else +cat << SENDMAIL_TEXT >> "$TXT_CFG" +MAILPROGRAM =$TWMAILPROGRAM +SENDMAIL_TEXT +fi + +if [ ! -s "$TXT_CFG" ] ; then + echo "Error: unable to create $TXT_CFG" + exit 1 +fi + +chmod 640 "$TXT_CFG" + +##======================================================= +## Create signed tripwire configuration file. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Creating signed configuration file..." + +##------------------------------------------------------- +## If noclobber, then backup any existing config file. +##------------------------------------------------------- + +if [ "$CLOBBER" = "false" ] && [ -s "$CONFIG_FILE" ] ; then + backup="${CONFIG_FILE}.$$.bak" + echo "Backing up $CONFIG_FILE" + echo " to $backup" + `mv "$CONFIG_FILE" "$backup"` + if [ $? -ne 0 ] ; then + echo "Error: backup of configuration file failed." + exit 1 + fi +fi + +##------------------------------------------------------- +## Build command line. +##------------------------------------------------------- + +cmdargs="--create-cfgfile" +cmdargs="$cmdargs --cfgfile \"$CONFIG_FILE\"" +cmdargs="$cmdargs --site-keyfile \"$SITE_KEY\"" +if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" +fi + +##------------------------------------------------------- +## Sign the file. +##------------------------------------------------------- + +eval "\"$TWADMIN\" $cmdargs \"$TXT_CFG\"" +if [ $? -ne 0 ] ; then + echo "Error: signing of configuration file failed." + exit 1 +fi + +# Set the rights properly +chmod 640 "$CONFIG_FILE" + +##------------------------------------------------------- +## We keep the cleartext version around. +##------------------------------------------------------- + +cat << END_OF_TEXT + +A clear-text version of the Tripwire configuration file +$TXT_CFG +has been preserved for your inspection. It is recommended +that you delete this file manually after you have examined it. + +END_OF_TEXT + +##======================================================= +## Modify default policy file with file locations +##======================================================= + +echo +echo "----------------------------------------------" +echo "Customizing default policy file..." + +sed '/@@section GLOBAL/,/@@section FS/ { + s?^\(TWROOT=\).*$?TWDOCS='\""$TWDOCS"\"';? + s?^\(TWBIN=\).*$?\1'\""$TWBIN"\"';? + s?^\(TWPOL=\).*$?\1'\""$TWPOLICY"\"';? + s?^\(TWDB=\).*$?\1'\""$TWDB"\"';? + s?^\(TWSKEY=\).*$?\1'\""$TWSITEKEYDIR"\"';? + s?^\(TWLKEY=\).*$?\1'\""$TWLOCALKEYDIR"\"';? + s?^\(TWREPORT=\).*$?\1'\""$TWREPORT"\"';? + s?^\(HOSTNAME=\).*$?\1'"$HOST_NAME"';? +}' "${TWPOLICY}/${POLICYSRC}" > "${TXT_POL}.tmp" + +# copy the tmp file back over the default policy +[ -f "${TXT_POL}" ] && cp "${TXT_POL}" "${TXT_POL}.bak" +mv "${TXT_POL}.tmp" "${TXT_POL}" +rm -f "${TWPOLICY}/${POLICYSRC}" + +# reset rights on the policy files to 640 +[ -f "${TXT_POL}" ] && chmod 640 "$TXT_POL" +[ -f "${TXT_POL}.bak" ] && chmod 640 "${TXT_POL}.bak" + + +##======================================================= +## Create signed tripwire policy file. +##======================================================= + +echo +echo "----------------------------------------------" +echo "Creating signed policy file..." + +##------------------------------------------------------- +## If noclobber, then backup any existing policy file. +##------------------------------------------------------- + +if [ "$CLOBBER" = "false" ] && [ -s "$POLICY_FILE" ] ; then + backup="${POLICY_FILE}.$$.bak" + echo "Backing up $POLICY_FILE" + echo " to $backup" + mv "$POLICY_FILE" "$backup" + if [ $? -ne 0 ] ; then + echo "Error: backup of policy file failed." + exit 1 + fi +fi + +##------------------------------------------------------- +## Build command line. +##------------------------------------------------------- + +cmdargs="--create-polfile" +cmdargs="$cmdargs --cfgfile \"$CONFIG_FILE\"" +cmdargs="$cmdargs --site-keyfile \"$SITE_KEY\"" +if [ -n "$TW_SITE_PASS" ] ; then + cmdargs="$cmdargs --site-passphrase \"$TW_SITE_PASS\"" +fi + +##------------------------------------------------------- +## Sign the file. +##------------------------------------------------------- + +eval "\"$TWADMIN\" $cmdargs \"$TXT_POL\"" +if [ $? -ne 0 ] ; then + echo "Error: signing of policy file failed." + exit 1 +fi + +# Set the proper rights on the newly signed policy file. +chmod 0640 "$POLICY_FILE" + +##------------------------------------------------------- +## We keep the cleartext version around. +##------------------------------------------------------- + +cat << END_OF_TEXT + +A clear-text version of the Tripwire policy file +$TXT_POL +has been preserved for your inspection. This implements +a minimal policy, intended only to test essential +Tripwire functionality. You should edit the policy file +to describe your system, and then use twadmin to generate +a new signed copy of the Tripwire policy. + +END_OF_TEXT + +##======================================================= +## Clean-up. +##======================================================= + +cat << END_OF_TEXT + +---------------------------------------------- +The installation succeeded. + +Please refer to $README_LOC +for release information and to the printed user documentation +for further instructions on using Tripwire 2.4 Open Source. + +END_OF_TEXT + +cd "$START_DIR" + diff --git a/lib/.keepme b/lib/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..f070115 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,12 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +SUBDIRS = man4 man5 man8 + +#man_MANS = \ +# ./man4/twconfig.4 \ +# ./man4/twpolicy.4 \ +# ./man5/twfiles.5 \ +# ./man8/siggen.8 \ +# ./man8/tripwire.8 \ +# ./man8/twadmin.8 \ +# ./man8/twintro.8 \ +# ./man8/twprint.8 diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 0000000..790fbe3 --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,458 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = man +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +SUBDIRS = man4 man5 man8 +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || mkdir "$(distdir)/$$subdir" \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="../$(top_distdir)" \ + distdir="../$(distdir)/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-recursive distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-info-am + + +#man_MANS = \ +# ./man4/twconfig.4 \ +# ./man4/twpolicy.4 \ +# ./man5/twfiles.5 \ +# ./man8/siggen.8 \ +# ./man8/tripwire.8 \ +# ./man8/twadmin.8 \ +# ./man8/twintro.8 \ +# ./man8/twprint.8 +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/man4/Makefile.am b/man/man4/Makefile.am new file mode 100644 index 0000000..5cd3a16 --- /dev/null +++ b/man/man4/Makefile.am @@ -0,0 +1,2 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = twconfig.4 twpolicy.4 diff --git a/man/man4/Makefile.in b/man/man4/Makefile.in new file mode 100644 index 0000000..8956e1a --- /dev/null +++ b/man/man4/Makefile.in @@ -0,0 +1,360 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = man/man4 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +man4dir = $(mandir)/man4 +am__installdirs = "$(DESTDIR)$(man4dir)" +NROFF = nroff +MANS = $(man_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = twconfig.4 twpolicy.4 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/man4/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/man4/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-man4: $(man4_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man4dir)" || $(mkdir_p) "$(DESTDIR)$(man4dir)" + @list='$(man4_MANS) $(dist_man4_MANS) $(nodist_man4_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.4*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 4*) ;; \ + *) ext='4' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man4dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man4dir)/$$inst"; \ + done +uninstall-man4: + @$(NORMAL_UNINSTALL) + @list='$(man4_MANS) $(dist_man4_MANS) $(nodist_man4_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.4*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 4*) ;; \ + *) ext='4' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man4dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man4dir)/$$inst"; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man4dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man4 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man4 + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man4 install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-info-am uninstall-man uninstall-man4 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/man4/twconfig.4 b/man/man4/twconfig.4 new file mode 100644 index 0000000..80f7d40 --- /dev/null +++ b/man/man4/twconfig.4 @@ -0,0 +1,300 @@ +.\" Macros added by addw@phcomp.co.uk for those systems where the an +.\" troff macro package doesn't know about .Ps & .Pe. +.\" Note it is assumed that CW is a constant width font. +.\" Ps - Start display text +.de Ps +.nf +.in +0.5i +.ft CW +.. +.\" Pe - end of display text +.de Pe +.fi +.in -0.5i +.ft 1 +.. +.\" +.\" Macros added by TSS. +.\" Nf - no fill, use constant width font +.\" Fi - fill, restore previous font +.\" Register Ni holds indent to use for Nf sections in points. +.nr Ni 30 +.de Nf +.nr OF \\n(.f +.nr OS \\n(.s +.ps \\n(.s-1 +.ft CW +.in +\\n(Nip +.nf +.. +.de Fi +.fi +.ft \\n(OF +.ps \\n(OS +.in -\\n(Nip +.. +.nh +.ad l +.TH TWCONFIG 4 "1 July 2000" +.SH NAME +twconfig \- \fITripwire\fP configuration file reference +.SH DESCRIPTION +.PP +The configuration file stores system-specific information, including the +location of \fITripwire\fP data files, and the settings used to send +email notification. The configuration file settings are +generated during the installation process, but can be changed by the system +administrator at any time. The configuration file is +signed with the site key, and the site passphrase is +required to edit the file. +.PP +During installation, a signed \fITripwire\fP configuration file \fItw.cfg\fP will be created in the \fI/etc/tripwire\fP directory, and a plain text copy of this configuration file \fItwcfg.txt\fP will be created in the same directory. +.PP +The configuration file is modified using the +.B twadmin\ \(hy\(hycreate\(hycfgfile +command. With this command, the user can designate +an existing plain text file as the current configuration file. +Using the current site key and passphrase, the new configuration file +is cryptographically signed and saved with this command. +.\" +.SS Components of the Configuration File +The \fITripwire\fP configuration file is structured as a list of +keyword-value pairs, and may also contain comments and variable +definitions. Any lines with "#" in the first column are treated as +comments. +.PP +The general syntax for variable definition is: +.br +.in +\n(Nip +.nf +\fIkeyword\fP = \fIvalue\fP +.fi +.in +For example: +.Nf +ROOT = /usr/tripwire +EDITOR = /usr/local/bin/jove +.Fi +.PP +Variable substitution on the right hand side is permitted using the syntax: +.br +.in +\n(Nip +.nf +$(\fI varname \fP) +.fi +.in +For example: +.Nf +DBFILE = $(ROOT)/db/$(HOSTNAME).twd +.Fi +.PP +Variable names are case-sensitive, and may contain all alphanumeric +characters, underscores, the characters "+\(hy@:", and the period. +Two variables are predefined in the configuration file, and may +not be changed. \f(CWHOSTNAME\fP is the +unqualified hostname that \fITripwire\fP is running on, and +\fR\f(CWDATE\fP +is a string representation of the date and time. +.SS Required Variables +The following variables must be set in order for \fITripwire\fP to +operate. The values listed below are assigned during installation. +.PP +.if n .nr Ti \n(.i +.Nf +.if n .in 0 +POLFILE Default = /etc/tripwire/tw.pol +DBFILE Default = /var/lib/tripwire/$(HOSTNAME).twd +REPORTFILE Default = /var/lib/tripwire/report/$(HOSTNAME)-$(DATE).twr +SITEKEYFILE Default = /etc/tripwire/site.key +LOCALKEYFILE Default = /etc/tripwire/$(HOSTNAME)-local.key +.Fi +.if n .in +\n(Tiu +.SS Other Variables +The following variables are not required to run \fITripwire\fP, but +some of the program's functionality will be lost without them. The +values assigned during installation are listed. +.IP \f(CWEDITOR\fP +Specifies an editor to be used in interactive modes. If \fIEDITOR\fP +is not defined, and no editor is specified on the command line, using +interactive modes will cause an error. +.br +Initial value: \fI/bin/vi\fP +.IP \f(CWTEMPDIRECTORY\fP +This variable can be set to the location to which tripwire should write +its temporary files. By default it is /tmp, which due to the default +permissions can be very insecure. It is recommended that you use this +configuration variable to provide tripwire with a secure place to write +temporary files. The directory used should have its permissions set such +that only the owning process can read/write to it, i.e. "chmod 700". +.br +Initial value: \fI/tmp\fP +.IP \f(CWGLOBALEMAIL\fP +This variable is set to a list of email addresses separated by either +a comma ",", or semi-colon ";". If a report would have normally been +sent out, it will also be send to this list of recipients. +.br +Initial value: \fInone\fP +.IP \f(CWLATEPROMPTING\fP +Prompt for passphrase as late as possible to minimize the amount of +time that the passphrase is stored in memory. If the value is +\fItrue\fP (case-sensitive), then late prompting is turned on. With +any other value, or if the variable is removed from the configuration +file, late prompting is turned off. +.br +Initial value: \fIfalse\fP +.IP \f(CWLOOSEDIRECTORYCHECKING\fP +When a file is added or removed from a directory, \fITripwire\fP +reports both the changes to the file itself, and the modification to +the directory (size, num links, etc.). This can create redundant +entries in \fITripwire\fP reports. With loose directory checking, +Tripwire will not check directories for any properties that would +change when a file was added or deleted. This includes: size, number +of links, access time, change time, modification time, number of blocks, +growing file, and all hashes. +.IP \ \ \ +If the value for this variable is \fItrue\fP (case-sensitive), +then loose directory checking is turned on, and these +properties will be ignored for all directories. With any other value, +or if the variable is removed from the configuration file, loose +directory checking is turned off. Turning loose directory checking +on is equivalent to appending the following propertymask to +the rules for all directory inodes: +.ft CW +.ps \n(.s-1 +\(hysnacmblCMSH +.ps \n(.s+1 +.ft R +.br +Initial value: \fIfalse\fP +.IP \f(CWSYSLOGREPORTING\fP +If this variable is set to \fItrue\fR, messages are sent +to the syslog for four events: database initialization, +integrity check completions, database updates, and policy updates. +The syslog messages are sent from the "user" facility at +the "notice" level. For more information, see the +.BR syslogd (1) +man page and the +.I syslog.conf +file. The following illustrates the information logged +in the syslog for each of the four events: +.if n .nr Ti \n(.i +.Nf +.if n .in 0 + +Jun 18 14:09:42 lighthouse tripwire[9444]: Database initialized: +/var/lib/tripwire/test.twd + +Jun 18 14:10:57 lighthouse tripwire[9671]: Integrity Check Complete: +TWReport lighthouse 20000618141057 V:2 S:90 A:1 R:0 C:1 + +Jun 18 14:11:19 lighthouse tripwire[9672]: Database Update Complete: +/var/lib/tripwire/test.twd + +Jun 18 14:18:26 lighthouse tripwire[9683]: Policy Update Complete: +/var/lib/tripwire/test.twd + +.Fi +.if n .in +\n(Tiu +The letters in the Integrity Checking log correspond to # of +violations, maximum severity level, and # of files added, +deleted, and changed, +respectively. With any value other than \fItrue\fR, or if this +variable is removed from the configuration file, syslog reporting will +be turned off. +.br +Initial value: \fItrue\fP +.IP \f(CWREPORTLEVEL\fP +Specifies the default level of report produced by the \fBtwprint +\(hy\(hyprint\(hyreport\fP mode. Valid values for this option are 0 to +4. The report +level specified by this option can be overridden with the (\fB\(hyt\fP\ or\ \fB\(hy\(hyreport\(hylevel\fP) option on the command line. If +this variable is not included in the configuration file, the default +report level is 3. Note that only reports printed using the +\fBtwprint\ \(hy\(hyprint\(hyreport\fP mode are affected by this +parameter; reports displayed by other modes and other commands +are not affected. +.br +Initial value: \fI3\fP +.SS Email Notification Variables +.IP \f(CWMAILMETHOD +Specifies the protocol to be used by \fITripwire\fR for email +notification. The only acceptable values for this field are +\fR\f(CWSMTP\fP or \f(CWSENDMAIL\fP. Any other value will +produce an error message. +.br +Initial value: \fISENDMAIL\fP +.IP \f(CWSMTPHOST +Specifies the domain name or IP address of the SMTP server used for +email notification. Ignored unless \f(CWMAILMETHOD\fP is set to +\f(CWSMTP\fP. +.br +Initial value: \fImail.domain.com\fP +.IP \f(CWSMTPPORT +Specifies the port number used with SMTP. Ignored unless +\f(CWMAILMETHOD\fP is set to \f(CWSMTP\fP. +.br +Initial value: \fI25\fP +.IP \f(CWMAILPROGRAM\fP +Specifies the program used for email reporting of rule violations if +\f(CWMAILMETHOD\fP is set to \f(CWSENDMAIL\fP. The program must take +an RFC822 style mail header, and recipients will be listed in the "To:" +field of the mail header. Some mail programs interpret a line +consisting of only a single period character to mean +end\(hyof\(hyinput, and all text after that is ignored. Since there is +a small possibility that a +.I Tripwire +report would contain such a line, the mail program specified must be +able to ignore lines that consist of a single period (the \fB-oi\fP +option to sendmail produces this behavior). +.br +Initial value: \fI/usr/lib/sendmail -oi -t\fP +.IP \f(CWEMAILREPORTLEVEL\fP +Specifies the default level of report produced by the \fBtripwire +\(hy\(hycheck\fP mode email report. Valid values for this option are 0 +to 4. The +report level specified by this option can be overridden with the +(\fB\(hyt\fP\ or\ \fB\(hy\(hyemail\(hyreport\(hylevel\fP) option on the +command\(hyline. If this variable is not included in the configuration +file, the default report level is 3. +.br +Initial value: \fI3\fP +.IP \f(CWMAILNOVIOLATIONS\fP +This option controls the way that \fITripwire\fR sends email +notification if no rule violations are found during an integrity check. +If \fR\f(CWMAILNOVIOLATIONS\fP is set to \fIfalse\fP and no violations +are found, \fITripwire\fR will not send a report. With any other value, +or if the variable is removed from the configuration file, +\fITripwire\fR will send an email message stating that no violations +were found. +.IP \ \ \ +Mailing reports of no violations allows an administrator to distinguish +between unattended integrity checks that are failing to run and +integrity checks that are running but are not finding any violations. +However, mailing no violations reports will increase the amount of data +that must be processed. +.br +Initial value: \fItrue\fR +.SH VERSION INFORMATION +This man page describes +.IR "Tripwire 2.4" "." +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twadmin (8), +.BR twprint (8), +.BR siggen (8), +.BR twpolicy (4), +.BR twfiles (5), +.BR sendmail (1), +.BR vi (1), +.BR syslogd (1) diff --git a/man/man4/twpolicy.4 b/man/man4/twpolicy.4 new file mode 100644 index 0000000..d896ea7 --- /dev/null +++ b/man/man4/twpolicy.4 @@ -0,0 +1,548 @@ +.\" Macros added by addw@phcomp.co.uk for those systems where the an +.\" troff macro package doesn't know about .Ps & .Pe. +.\" Note it is assumed that CW is a constant width font. +.\" Ps - Start display text +.de Ps +.nf +.in +0.5i +.ft CW +.. +.\" Pe - end of display text +.de Pe +.fi +.in -0.5i +.ft 1 +.. +.\" +.\" Macros added by TSS. +.\" Nf - no fill, use constant width font +.\" Fi - fill, restore previous font +.\" Register Ni holds indent to use for Nf sections in points. +.nr Ni 36 +.de Nf +.nr OF \\n(.f +.nr OS \\n(.s +.ps \\n(.s-1 +.ft CW +.in +\\n(Nip +.nf +.. +.de Fi +.fi +.ft \\n(OF +.ps \\n(OS +.in -\\n(Nip +.. +.\" +.nh +.ad l +.TH TWPOLICY 4 "1 July 2000" +.SH NAME +twpolicy \- \fITripwire\fP policy file reference +.SH DESCRIPTION +.PP +The policy file describes system objects to be monitored by +\fITripwire\fP, and specifies what properties for each object should be +collected and stored in the database file. Each object in the policy +file is associated with a property mask, which describes what changes +to the file or directory \fITripwire\fP should monitor, and which ones +can safely be ignored. By customizing the various aspects of the +policy file, the system administrator can very closely control how +\fITripwire\fP checks the integrity of any system. +.PP +During installation, an encoded and signed policy file (\fItw.pol\fP) +will be created in the \fI/etc/tripwire\fP directory, +and a plain text copy of this policy file (\fItwpol.txt\fP) will be +generated in the same directory. An additional text file +(\fIpolicyguide.txt\fP) illustrates all of the features of the policy +language. Both of the text files are heavily commented and can be used +as a reference during policy file creation. +.PP +A new policy file is first created using the +\fBtwadmin\ \(hy\(hycreate\(hypolfile\fP +command. With this command, the +user can designate an existing plain text file as the current policy +file. Using the current site key and passphrase, the new configuration +file is encoded, signed and saved. +.PP +Once the initial policy file has been generated, any changes should be +made with the \fBtripwire\ \(hy\(hyupdate\(hypolicy\fP command, rather +than by simply overwriting the policy file with the +\fBtwadmin\ \(hy\(hycreate\(hypolfile\fP command. This is an important +.ie n distinction\(hy\(hywhen +.el distinction\(emwhen +a new policy file is created, the \fITripwire\fP +database must be re-initialized. If an intruder has modified files +since the last integrity check, these changes will not be detected, and +will be included as part of the new "baseline" database. +.\" +.SH COMPONENTS OF THE POLICY FILE +The basic components of policy files are comments, rules, directives, +and variables. Each of these components is described in greater detail +below. +.SS Comments +In a policy file, any text following a '#', up to the next line break, +is considered a comment. Example: +.PP +.Nf +# This is a comment. +/bin -> $(ReadOnly); # A comment can go here, too. +.Fi +.\" +.SS Rules +Policy rules determine whether and to what extent \fITripwire\fP will +check particular files and directories. There are two kinds of policy +rules recognized by \fITripwire\fP: +.PP +1) Normal rules define which properties of a particular file or +directory tree \fITripwire\fP scans. +.br +2) Stop points tell \fITripwire\fP not to scan a particular file or +directory. +.SS Normal Rules +The format for a normal rule is: +.br +.in +\n(Nip +\fIobject_name\fP -> \fIproperty_mask\fP; +.in +.PP +where the \fIobject_name\fP is the fully qualified pathname for a +directory or file, and \fIproperty_mask\fP +specifies what properties of an object to examine or ignore. +The '\(hy>' token separates the pathname and the property mask. +Whitespace must separate the object name and '\(hy>' token. +A semicolon must terminate the rule. If the +pathname specified is a directory, the directory and all of its +descendants will be scanned with the indicated property mask. If the +pathname refers to an individual file, only that file will be scanned +with the specified property mask. Examples: +.PP +.Nf +# Defines Tripwire behavior for entire /bin directory tree. +/bin -> $(ReadOnly); + +# Defines Tripwire behavior for a single file. In this case, +# Tripwire watches for all properties of hostname.hme0. +/etc/hostname.hme0 -> $(IgnoreNone) -ar; + +# Scan the entire /etc directory tree using mask1, except the +# file /etc/passwd, which should be scanned using mask2. +/etc -> $(mask1); +/etc/passwd -> $(mask2); +.Fi +.PP +Only one rule may be associated with any given object. If any object +has more than one rule in a policy file, \fITripwire\fP will print an +error message and exit without scanning any files. For example: +.PP +.Nf +# This is an example of an illegal construct. +/usr/bin -> $(mask3); +/usr/bin -> $(mask4); +.Fi +.PP +.\" +.SS Object Names +In this document, policy file objects are fully qualified pathnames of +files and directories. Environment variables are not allowed for +security reasons. Examples: +.PP +.Nf +/etc # valid object name. +/etc/passwd # valid object name. +$HOME # not valid. +.Fi +.\" +.SS Property Masks +Property masks designate which \fITripwire\fP properties of a given +object should be examined. A property mask consists of a series of +single-character symbols, each of which may be preceded by an optional +plus or minus sign. Each character symbol stands for a particular +\fITripwire\fP property to be examined during integrity checking. If +the character is preceded by a plus, checking is done for that +property; if preceded by a minus, checking is not done for that +property. For example: +.PP +.Nf +\+p # compare permissions. +\-p # ignore permissions. +.Fi +.PP +Each rule in the policy file must have a property mask. Examples: +.PP +.Nf +/etc -> $(IgnoreAll); #valid property mask. +/etc -> +p-p; #valid property mask. +/etc -> ; #invalid property mask. +.Fi +.PP +Characters in a property mask without a preceding plus or minus sign +are assumed to be plus. If a property is not specified in the property +mask, it is ignored, which is equivalent to turning it off with +the minus sign. Examples: +.PP +.Nf +# Examine permissions and link count. +# All three of the following are equivalent. ++p+n +pn +pn-g +.Fi +.PP +Characters used in property masks, with descriptions: +.PP +.Nf +\- Ignore the following properties +\+ Record and check the following properties +a Access timestamp +b Number of blocks allocated +c Inode timestamp (create/modify) +d ID of device on which inode resides +g File owner's group ID +i Inode number +l File is increasing in size (a "growing file") +m Modification timestamp +n Number of links (inode reference count) +p Permissions and file mode bits +.if t r ID of device pointed to by inode (valid only for device objects) +.if n r ID of device pointed to by inode +.if n \ (valid only for device objects) +s File size +t File type +u File owner's user ID +C CRC-32 hash value +H Haval hash value +M MD5 hash value +S SHA hash value +.Fi +.\" +.SS Stop Points +Stop points are used to specify specific files or directories that +\fITripwire\fP should not scan. The syntax for stop points is: +.br +.in +\n(Nip +.nf +\&! \fIobject_name\fP ; +.fi +.in +For example: +.Nf +!/etc/init.d; +# The directory /etc/init.d will not be scanned. + +/etc -> $(ReadOnly); +!/etc/rc.d; +!/etc/mnttab; +# Scan all of /etc, but do not scan two particular +# files in the /etc hierarchy. +.Fi +.\" +.SS Rule Attributes +Rule attributes work with normal rules to modify their behavior or +provide additional information. Multiple attributes can be assigned to +each rule. Rule attributes are not case-sensitive. +Rule attributes may be applied to a single rule +using the following syntax: +.br +.in +\n(Nip +\fIobject_name\fP -> \fIproperty_mask\fP (\fIrule attribute\fP = \fIvalue\fP); +.in +For example: +.Nf +/usr/lib -> $(ReadOnly) (emailto = admin@foo.com, severity = 80); +#This rule will notify the admin if any violations of the +#rule occur and designate the severity as 80. +.Fi +.PP +Rule attributes can also be specified for a group of rules, +using the format: +.br +.in +\n(Nip +(\fIattribute list\fP) +.br +{ +.in +\n(Nip +\fIrule list\fP; +.in -\n(Nip +} +.in -\n(Nip +For example: +.Nf +(emailto = admin@foo.com, severity = 80) +{ + /usr/lib -> $(ReadOnly); +} +.Fi +is equivalent to the attribute example above. +.PP +The following four rule attributes are supported by \fITripwire\fP: +./" +.IP \f(CWrulename\fP 15 +The \f(CWrulename\fP attribute is used to associate a rule or set +of rules with a specific name. In a report file, this name will be +associated with violations to the specified rule. This feature is +useful if you want to track certain objects within a large +\fITripwire\fP database. For instance, if you associate the rule name +"watchme" with important files, you can sort through the \fITripwire\fP +report using "watchme" as a sorting key. +.br +Example: +.Nf +/etc -> +ug (rulename=watchme); +.Fi +./" +.IP \f(CWemailto\fP 15 +The \f(CWemailto\fP attribute associates one or more email addresses +with a rule or group of rules. When an integrity check is run with the +.B \(hy\(hyemail\(hyreport +option and a rule is violated, a report of that violation will be sent +to the specified email address(es), using the report format specified +by the +.\" Do not remove the \fR at the start of the following line. +.\" Formatting weirdness results otherwise on AIX. +\fR\f(CWEMAILREPORTLEVEL\fP variable in the configuration file. +.br +Example: +.Nf +/etc -> +ug (emailto=admin@domain.com); +.Fi +.IP +To specify multiple email addresses, include them as a quoted, +semicolon-delimited list. +.Nf +.if n .in -\n(Nip +/etc -> +ug (emailto="admin@foo.com;admin2@foo.com"); +.if n .in +\n(Nip +.Fi +./" +.IP \f(CWseverity\fP 15 +The \f(CWseverity\fP attribute associates a numeric severity level with +a rule. When \fITripwire\fP is run in Integrity Checking mode, it is +possible to specify that only rules exceeding a certain severity level +are used. The default severity level is 0, and values can range from 0 +to 1,000,000. +.br +Example: +.Nf +/etc -> +ug (severity=50); +.Fi +./" +.IP \f(CWrecurse\fP 15 +The \f(CWrecurse\fP attribute specifies how a rule will scan +directories. Valid values for \f(CWrecurse\fP are \fItrue\fR, +\fIfalse\fR, or a number from -1 to 1,000,000. If \fR\f(CWrecurse\fP is set +to \fItrue\fR (or\ \(hy1), tripwire will recursively scan the entire +contents of the directory (both files and subdirectories). When +\fR\f(CWrecurse\fP is set to \fIfalse\fR (or\ 0), and the rule refers to a +directory, \fITripwire\fP will scan the inode of the directory but none +of the files or subdirectories contained therein. For positive +\fR\f(CWrecurse\fP value \fIn\fR, the rule will monitor all objects up to +\fIn\fR levels below the start point. Stop points within the recursed +directory still apply, and will prevent the specified file or directory +from being scanned. +.IP +When a rule refers to a file, specifying the \f(CWrecurse\fP attribute +has no +.ie n effect\(hy\(hyfiles +.el effect\(emfiles +will be scanned no matter what value is given for +\f(CWrecurse\fP. The default value for \f(CWrecurse\fP is \fItrue\fR. +.br +Example: +.Nf +/etc -> +ug (recurse=2); +.Fi +./" +.SS Directives +\fITripwire\fP supports a small number of directives that allow +conditional interpretation of the policy file and certain diagnostic +and debugging operations. The primary purpose of directives is to +support sharing of a policy file among multiple machines. Directives +use the following syntax: +.br +.in +\n(Nip +.nf +@@ \fIdirective_name\fP [\fIarguments\fP] +.fi +.in +.PP +Where the directive name is one of the directives listed below: +.PP +.Nf +@@section # Designates a section of the policy file. + +@@ifhost # Allow conditional interpretation +@@else # of the policy file. +@@endif + +@@print # Print a message to standard output. +@@error # Print a message to standard output and then exit. + +@@end # Marks the logical end-of-file. +.Fi +.PP +The @@section directive is used to designate sections of the policy +file that are OS-specific. With \fITripwire 2.4\fP, valid +arguments for the @@section directive are +.\" Do not remove the \fR at the start of the following line. +.\" Formatting weirdness results otherwise on AIX. +\fR\f(CWFS\fP +and \f(CWGLOBAL\fP. If no @@section +directive is specified, \f(CWFS\fP will be assumed. +If the argument to the @@section directive is either +\f(CWNTFS\fP or \f(CWNTREG\fP (which have meaning only on +Windows NT systems), +\fITripwire\fP will skip all policy file text down to the +next valid @@section directive. Any other argument will +cause an error. +.PP +The @@ifhost, @@else, and @@endif directives are used to allow +conditional interpretation of the policy file. With the @@ifhost +directive, multiple hostnames can be expressed as arguments, but they +must be separated by an '||', interpreted as the logical 'OR'. This example illustrates how one might employ directives to use one policy file with multiple hosts. +.PP +.Nf +@@ifhost spock || kirk + /bin -> $(ReadOnly); +@@endif + +@@ifhost chekov || uhura + /usr/bin -> +pinug; +@@else + /usr/bin -> +pinugsmC; +@@endif +.Fi +.PP +The @@print and @@error directives are intended for debugging and remote +diagnostics. The syntax for these commands is: +.br +.in +\n(Nip +.nf +@@print "\fIstring\fP" +@@error "\fIstring\fP" +.fi +.in +.PP +The @@print directive prints \fIstring\fP to \fIstdout\fP, while the +@@error directive prints \fIstring\fP to \fIstdout\fP and causes the +calling program to exit with a non-zero status. +.PP +The @@end directive marks the end of the policy file. Any text +appearing after this directive will be ignored by \fITripwire\fP. +.\" +.SS Variables +For user convenience, \fITripwire\fP's policy file supports variables +for string substitution. Variables can be defined anywhere between +rules. The syntax for variable definition is: +.br +.in +\n(Nip +.nf +\fIvariable\fP = \fIvalue\fP; +.fi +.in +.PP +Variable substitution is legal anywhere that a string could appear. +The syntax for variable substitution is: +.br +.in +\n(Nip +.nf +$( \fIvariable\fP ) +.fi +.in +.PP +Examples of variable definition and variable substitution on the left, +right, and both sides of rules. Note that variable names are +case sensitive. +.PP +.Nf +param1 = +SMCH; # Set variable param1. +dir1 = /etc/inet; # Set variable dir1. +DIR1 = /etc/init.d; # Variables are case sensitive. +$(dir1) -> +tbamc; # Left hand substitution. +/etc/inet -> $(param1); # Right hand substitution. +$(DIR1) -> $(param1); # Double substitution. +.Fi +.PP +A number of variables are predefined by \fITripwire\fP and may not be +changed. These variables represent different ways that files can +change, and can be used on the right side of rules to design a policy +file quickly. +.IP ReadOnly 15 +ReadOnly is good for files that are widely available but are intended +to be read-only. +.br +Value: +.ft CW +.ps \n(.s-1 +\+pinugtsdbmCM\(hyrlacSH +.ps \n(.s+1 +.ft +.IP Dynamic 15 +Dynamic is good for monitoring user directories and files that tend to +be dynamic in behavior. +.br +Value: +.ft CW +.ps \n(.s-1 ++pinugtd\(hysrlbamcCMSH +.ps \n(.s+1 +.ft +.IP Growing 15 +The Growing variable is intended for files that should only get larger. +.br +Value: +.ft CW +.ps \n(.s-1 +\+pinugtdl\(hysrbamcCMSH +.ps \n(.s+1 +.ft +.IP Device 15 +Device is good for devices or other files that \fITripwire\fP should not +attempt to open. +.br +Value: +.ft CW +.ps \n(.s-1 +\+pugsdr\(hyintlbamcCMSH +.ps \n(.s+1 +.ft R +.IP IgnoreAll 15 +IgnoreAll tracks a file's presence or absence, but doesn't check any +other properties. +.br +Value: +.ft CW +.ps \n(.s-1 +\(hypinugtsdrlbamcCMSH +.ps \n(.s+1 +.ft +.IP IgnoreNone 15 +IgnoreNone turns on all properties and provides a convenient starting point for defining your own property masks. (For\ example,\ \f(CWmymask\ =\ $(IgnoreNone)\ -ar;\fP) +.br +Value: +.ft CW +.ps \n(.s-1 +\+pinugtsdrbamcCMSH\(hyl +.ps \n(.s+1 +.ft +.SH VERSION INFORMATION +This man page describes +.IR "Tripwire 2.4" "." +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twadmin (8), +.BR twprint (8), +.BR siggen (8), +.BR twconfig (4), +.BR twfiles (5) diff --git a/man/man5/Makefile.am b/man/man5/Makefile.am new file mode 100644 index 0000000..094ec74 --- /dev/null +++ b/man/man5/Makefile.am @@ -0,0 +1,2 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = twfiles.5 diff --git a/man/man5/Makefile.in b/man/man5/Makefile.in new file mode 100644 index 0000000..d0f4a69 --- /dev/null +++ b/man/man5/Makefile.in @@ -0,0 +1,360 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = man/man5 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +man5dir = $(mandir)/man5 +am__installdirs = "$(DESTDIR)$(man5dir)" +NROFF = nroff +MANS = $(man_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = twfiles.5 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/man5/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/man5/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-man5: $(man5_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(mkdir_p) "$(DESTDIR)$(man5dir)" + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \ + done +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man5dir)/$$inst"; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man5dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man5 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man5 + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man5 install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-info-am uninstall-man uninstall-man5 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/man5/twfiles.5 b/man/man5/twfiles.5 new file mode 100644 index 0000000..775e86b --- /dev/null +++ b/man/man5/twfiles.5 @@ -0,0 +1,123 @@ +.\" Macros added by addw@phcomp.co.uk for those systems where the an +.\" troff macro package doesn't know about .Ps & .Pe. +.\" Note it is assumed that CW is a constant width font. +.\" Ps - Start display text +.de Ps +.nf +.in +0.5i +.ft CW +.. +.\" Pe - end of display text +.de Pe +.fi +.in -0.5i +.ft 1 +.. +.\" +.\" Macro added by TSS. +.\" Ms - display subsection on two lines in nroff, one line in troff. +.de Ms +.ie n \{ .SS \\$1 +\\$2 +.br \} +.el .SS \\$1 (\\$2) +.. +.\" +.nh +.ad l +.TH TWFILES 5 "1 July 2000" +.SH NAME +twfiles \- overview of files used by \fITripwire\fR and file backup process +.\" +.SH DESCRIPTION +.\" +.Ms "Configuration File" "\fPdefault:\fP \fI/etc/tripwire/tw.cfg\fP" +The configuration file stores system-specific information, such as the +location of \fITripwire\fR data files. The configuration settings are +generated during the installation process, but can be changed by the system administrator at any time. See the +\fBtwconfig\fR(4) man page for a more complete discussion. +.\" +.Ms "Policy File" "\fPdefault:\fP \fI/etc/tripwire/tw.pol\fP" +The policy file consists of a series of rules specifying the system +objects that \fITripwire\fR should monitor, and the data for each +object that should be collected and stored in the database file. +Should unexpected changes occur, the policy file can describe the +person to be notified and the severity of the violation. See the +\fIpolicyguide.txt\fR file in the policy directory and the +\fBtwpolicy\fR(4) man page for a more complete discussion. +.\" +.Ms "Database File" "\fPdefault:\fP \fI/var/lib/$(HOSTNAME).twd\fP" +The database file serves as the +baseline for integrity checking. After installation, \fITripwire\fR +creates the initial database file, a "snapshot" of the filesystem in a +known secure state. Later, when an integrity check is run, +\fITripwire\fR compares each system object described in the policy file +against its corresponding entry in the database. A report is created, +and if an object has changed outside of constraints defined in the +policy file, a violation is reported. See the \fBtripwire\fR(8) and +\fBtwprint\fR(8) man pages for more information on creating and +maintaining database files. +.\" +.Ms "Report Files" "\fPdefault:\fP \fI/var/lib/tripwire/report/$(HOSTNAME)\(hy$(DATE).twr\fP" +Once the above three files have been created, \fITripwire\fR can run an +integrity check and search for any differences between the current +system and the data stored in the "baseline" \fITripwire\fR database. +This information is archived into report files, a collection of rule +violations discovered during an integrity check. +With the appropriate settings, a report can also be emailed to one +or more recipients. See the +\fBtripwire\fR(8) and \fBtwprint\fR(8) man pages for information on +creating and printing report files. +.\" +.Ms "Key Files" "\fPdefaults:\fP \fI/etc/tripwire/site.key\fP \fPand\fP \fI/etc/tripwire/$(HOSTNAME)\(hylocal.key\fP" +It is critical that \fITripwire\fR files be protected from unauthorized +.ie n access\(hy\(hyan +.el access\(eman +attacker who is able to modify these files can subvert \fITripwire\fR +operation. For this reason, all of the above files are +signed using public key cryptography to prevent unauthorized +modification. Two separate sets of keys protect critical \fITripwire\fR data files. One or both of these key sets is necessary for performing +almost every \fITripwire\fR task. +.PP +The site key is used to protect files that could be used across several +systems. This includes the policy and configuration files. The local +key is used to protect files specific to the local machine, such as the +\fITripwire\fR database. The local key may also be used for signing +integrity check reports. See the \fBtwadmin\fR(8) man page for more +information on keys. +.\" +.br +.br +.SS File Backup +To prevent the accidental deletion of important data, \fITripwire\fR +automatically creates backup files whenever any \fITripwire\fR file is +overwritten. The existing file will be renamed with a \fI.bak\fR +extension, and the new version of the file will take its place. Only +one backup copy for each filename can exist at any time. If a backup +copy of a file already exists, the older backup file will be deleted +and replaced with the newer one. +.PP +File backup is an integral part of \fITripwire\fR, and cannot be +removed or changed. +.SH VERSION INFORMATION +This man page describes +.IR "Tripwire 2.4" "." +.SH AUTHORS +Tripwire, Inc. +.\" +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twadmin (8), +.BR twprint (8), +.BR siggen (8), +.BR twconfig (4), +.BR twpolicy (4) diff --git a/man/man8/Makefile.am b/man/man8/Makefile.am new file mode 100644 index 0000000..12d65b4 --- /dev/null +++ b/man/man8/Makefile.am @@ -0,0 +1,2 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = siggen.8 tripwire.8 twadmin.8 twintro.8 twprint.8 diff --git a/man/man8/Makefile.in b/man/man8/Makefile.in new file mode 100644 index 0000000..54eb667 --- /dev/null +++ b/man/man8/Makefile.in @@ -0,0 +1,360 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = man/man8 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +man8dir = $(mandir)/man8 +am__installdirs = "$(DESTDIR)$(man8dir)" +NROFF = nroff +MANS = $(man_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +man_MANS = siggen.8 tripwire.8 twadmin.8 twintro.8 twprint.8 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/man8/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/man8/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-man8: $(man8_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man8dir)" || $(mkdir_p) "$(DESTDIR)$(man8dir)" + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \ + done +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man8dir)/$$inst"; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man8 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man8 + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man8 install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-info-am uninstall-man uninstall-man8 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/man8/siggen.8 b/man/man8/siggen.8 new file mode 100644 index 0000000..7b5b001 --- /dev/null +++ b/man/man8/siggen.8 @@ -0,0 +1,81 @@ +'\" t +.\" Do not move or remove previous line. +.\" Used by some man commands to know that tbl should be used. +.nh +.TH SIGGEN 8 "1 July 2000" +.SH NAME +siggen \- signature gathering routine for Tripwire +.SH SYNOPSIS +.B siggen +.RI "[ " "options..." " ]" +.IR file1 " [ " "file2..." " ] " + +.I Options: +.RS +0.5i +.TS +; +lbw(0.8i) lb. +-t --terse +-h --hexadecimal +-a --all +-C --CRC32 +-M --MD5 +-S --SHA +-H --HAVAL +.TE +.RE +.SH DESCRIPTION +.PP +\fBsiggen\fP is a utility that displays the hash function values +for the specified files. +.SH OPTIONS +.TP +.BI \(hyt ", " --terse +Terse mode. +Prints requested hashes for a given file on one line, delimited +by spaces, with no extraneous information. +.TP +.BI \(hyh ", " --hexadecimal +Display results in hexadecimal rather than base64 notation. +.TP +.BI \(hya ", " --all +Display all hash function values (default). +.TP +.BI \(hyC ", " --CRC32 +Display CRC-32, POSIX 1003.2 compliant 32-bit Cyclic Redundancy +Check. +.TP +.BI \(hyM ", " --MD5 +Display MD5, the RSA Data Security, Inc. Message Digest Algorithm. +.TP +.BI \(hyS ", " --SHA +Display SHA, \fITripwire\fP's implementation of the +NIST Secure Hash Standard, SHS (NIST FIPS 180). +.TP +.BI \(hyH ", " --HAVAL +Display Haval value, a 128-bit hash code. +.TP +.IR file1 " [ " "file2... " ] +List of filesystem objects for which to display values. +.SH VERSION INFORMATION +This man page describes +.B siggen +version 2.4. +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twadmin (8), +.BR twprint (8), +.BR twconfig (4), +.BR twpolicy (4), +.BR twfiles (5) diff --git a/man/man8/tripwire.8 b/man/man8/tripwire.8 new file mode 100644 index 0000000..fd539d3 --- /dev/null +++ b/man/man8/tripwire.8 @@ -0,0 +1,577 @@ +'\" t +.\" Do not move or remove previous line. +.\" Used by some man commands to know that tbl should be used. +.\" +.\" Macros added by addw@phcomp.co.uk for those systems where the an +.\" troff macro package doesn't know about .Ps & .Pe. +.\" Note it is assumed that CW is a constant width font. +.\" Ps - Start display text +.de Ps +.nf +.in +0.5i +.ft CW +.ps \\n(.s-1 +.. +.\" Pe - end of display text +.de Pe +.fi +.in -0.5i +.ft 1 +.ps \\n(OS +.. +.\" Macro added by TSS. +.\" The command mode descriptions run together visually, so +.\" macro Hr draws a horizontal rule to give some separation +.\" between modes. Register Vs dithers the amount of vertical +.\" space before the rule, in lines. +.nr Vs 1 +.de Hr +.ne \\n(Vs+2 +.sp \\n(Vsli +.nr Oi \\n(.i +.in 0 +\\l'\\n(.lu' +.in \\n(.iu +.. +.\" +.nh +.ad l +.TH TRIPWIRE 8 "1 July 2000" +.SH NAME +tripwire \- a file integrity checker for \s-1UNIX\s0 systems +.SH SYNOPSIS +.B tripwire +.RB "{ " "-m i" " | " "--init" " } " +.RI "[ " options... " ]" +.br +.B tripwire +.RB "{ " "-m c" " | " "--check" " } " +.RI "[ " options... " ] " +.if n .br +.if n .ti +.5i +.RI "[ " "object1" " [ " "object2..." " ]]" +.br +.B tripwire +.RB "{ " "-m u" " | " "--update" " } " +.RI "[ " options... " ]" +.br +.B tripwire +.RB "{ " "-m p" " | " "--update-policy" " } " +.RI "[ " options... " ]" +.if n .br +.if n .ti +.5i +.I policyfile.txt +.br +.B tripwire +.RB "{ " "-m t" " | " "--test" " } " +.RI "[ " options... " ]" +.\" +.SH DESCRIPTION +.\" +.SS Database Initialization Mode +Running \fBtripwire\fP in Database Initialization mode is +typically one of the first steps in setting up +\fITripwire\fR for regular operation. This mode creates a baseline +database in the location specified by the +.hy 0 +\fR\f(CWDBFILE\fP +.hy 1 +variable in the \fITripwire\fP configuration file. The +database is essentially a snapshot of the objects residing on the +system. During later \fITripwire\fP integrity checks, this database +serves as the basis for comparison. +.PP +When run in Database Initialization mode, \fBtripwire\fP reads the +policy file, generates a database based on its contents, and then +cryptographically signs the resulting database. Options can be entered +on the command line to specify which policy, configuration, and key +files are used to create the database. The filename for the database +can be specified as well. If no options are specified, the default +values from the current configuration file are used. +.\" +.\" ***************************************** +.SS Integrity Checking Mode +After building the \fITripwire\fP database, the next step is typically +to run \fBtripwire\fP in Integrity Checking mode. This mode scans the +system for violations, as specified in the policy file. Using the +policy file rules, \fITripwire\fP will compare the state of the current +file system against the initial baseline database. An integrity +checking report is printed to \fIstdout\fP and is saved in the +location specified by the +.hy 0 +\fR\f(CWREPORTFILE\fP +.hy 1 +setting in the \fITripwire\fR configuration file. +.PP +The generated report describes each policy file violation in detail, +depending on whether the specified file system object was added, +deleted, or changed. Each report item lists the properties of the +object as it currently resides on the file system, and, if appropriate, +the old value stored in the database. If there are differences between +the database and the current system, the administrator can either fix +the problem by replacing the current file with the correct file (e.g., +an intruder replaced \fI/bin/login\fP), or update the database to +reflect the new file (e.g., a fellow system administrator installed a +new version of \fI/usr/local/bin/emacs\fP). The (\fB\(hyI\fP or +\fB\(hy\(hyinteractive\fP) option launches an editor that allows the +user to update the database quickly. The Database Update mode of +\fBtripwire\fP can also be used. +.\" +.\" ***************************************** +.SS Database Update Mode +Running \fBtripwire\fP in Database Update mode allows any differences +between the database and the current system to be reconciled. This +will prevent the violation from showing up in future reports. If the +reported change is unexpected and potentially malicious, then the +changed file should be replaced with the original version. If there is +a valid reason for the change, the database must be changed to match +the current files. +.PP +In Database Update mode, the items to be changed are specified in a +"ballot box" in the plain text report +that is launched in an editor program. +The entries to +be updated are specified by leaving the "x" next to each policy +violation. After the user exits the editor and provides the correct +local passphrase, +\fBtripwire\fP will update the database. +Options to control this operation include the +.hy 0 +(\fB\(hyZ\fP\ or\ \fB\(hy\(hysecure\(hymode\fP) and (\fB\(hya\fP\ or\ \fB\(hy\(hyaccept\(hyall\fP) flags. +.hy 1 +.\" +.\" ***************************************** +.SS Policy Update Mode +Policy update mode is used by \fBtripwire\fP to change or update the +policy file and to synchronize an earlier database with new policy +file information. The filename of the new clear text version of the +policy file is specified on the command line. The new policy file is +compared to the existing version, and the database is updated according +to the new policy rules. Any changes in the database since the last +integrity check will be detected and reported. How these violations +are interpreted depends on the security mode specified with the +(\fB\(hyZ\fP or \fB\(hy\(hysecure\(hymode\fP) option. +In \fBhigh\fP security mode (the default), \fITripwire\fR will print a list of +violations and exit without making changes to the database. In +\fBlow\fP security mode, the violations are still +reported, but changes to the database are made automatically. +.PP +Because the policy and database files are binary-encoded and +cryptographically signed, the user will be prompted for the site and +local passphrases to change the policy settings. After the database is +successfully updated, the +database and policy files are re-encoded and signed. +.\" +.\" ***************************************** +.SS Test Mode +Test mode is used to check the operation of the \fITripwire\fR email +notification system. When run in this mode, \fITripwire\fR will use the +email notification settings specified in the configuration file to send +a test email message. If MAILMETHOD is set to SMTP, the SMTPHOST and +SMTPPORT values will be used to send email. If MAILMETHOD is set to +SENDMAIL, the MAILPROGRAM value will be used. If email notification is +working correctly, the address specified on the command line will +receive the following message: +.PP +.Ps +To: user@domain.com +From: user +Subject: Test email message from Tripwire + +If you receive this message, email notification +from Tripwire is working correctly. +.Pe +.PP +Test mode only tests email notification for the address specified on +the command-line, and does not check for errors in the syntax used with +the \f(CWemailto\fP attribute in the policy file. +.if \n(.t<700 .bp +.SH OPTIONS +.\" +.\" ***************************************** +.SS Database Initialization mode: +.\" +.\" +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m i --init +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-d \fIdatabase\fP --dbfile \fIdatabase\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-e --no-encryption +.TE +.RE +.TP +.BR "\(hym i" ", " --init +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile" +Use the specified policy file. +.TP +.BI \(hyd " database\fR, " --dbfile " database" +Write to the specified database file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file to read the configuration and policy +files. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to write the new database file. +Mutually exclusive with (\fB\(hye\fR). +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specifies passphrase to be used with local key to sign the new database. +Mutually exclusive with (\fB\(hye\fR). +.TP +.BR \(hye ", " --no-encryption +Do not sign the database being stored. +The database file will still be compressed and will not be +human-readable. +Mutually exclusive with (\fB\(hyL\fR) and (\fB\(hyP\fR). +.\" +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Integrity Checking mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m c --check +-I --interactive +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-d \fIdatabase\fP --dbfile \fIdatabase\fP +-r \fIreport\fP --twrfile \fIreport\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-n --no-tty-output +-V \fIeditor\fP --visual \fIeditor\fP +-E --signed-report +-i \fIlist\fP --ignore \fIlist\fP +-l \fR{ \fIlevel\fR | \fIname\fR }\fP --severity \fR{ \fIlevel\fR | \fIname\fR }\fP +-R \fIrule\fP --rule-name \fIrule\fP +-x \fIsection\fP --section \fIsection\fP +-M --email-report +-t \fR{ 0|1|2|3|4 }\fP --email-report-level \fR{ 0|1|2|3|4 }\fP +.TE +.RI "[ " object1 " [ " object2... " ]]" +.RE +.TP +.BR "\(hym c" ", " --check +Mode selector. +.TP +.BR \(hyI ", " --interactive +At the end of integrity checking, the resulting report is opened +in an editor where database updates can be easily specified using +the ballot boxes included in the report. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile +Use the specified policy file. +.TP +.BI \(hyd " database\fR, " --dbfile " database" +Use the specified database file. +.TP +.BI \(hyr " report\fR, " --twrfile " report" +Write the specified report file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file to read the configuration +and policy files. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to read the database +file and, if (\fB\(hyE\fR) is specified, to write the report file. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specifies passphrase to be used with local key to +sign the database when (\fB\(hyI\fR) is used, and to +sign the report when (\fB\(hyE\fR) is used. +Valid only with (\fB\(hyI\fR) or (\fB\(hyE\fR). +.TP +.BR \(hyn ", " --no-tty-output +Suppress the report from being printed at the console. +.TP +.BI \(hyV " editor\fR, " --visual " editor +Use the specified editor to edit the update ballot boxes. +Meaningful only with (\fB\(hyI\fP). +.TP +.BR \(hyE ", " --signed-report +Specifies that the \fITripwire\fR report will be signed. If +no passphrase is specified on the command line, \fBtripwire\fR +will prompt for the local passphrase. +.TP +.BI \(hyi " list\fR, " --ignore " list +Do not compute or compare the properties specified in \fIlist\fR. Any +of the letter codes (abcdgimnprstulCHMS) specified in propertymasks can +be excluded. +Use of this option overrides information from the policy file. +The format to be used for \fIlist\fP is a double-quoted, comma-delimited list +of properties (e.g.\ \fI\-\-ignore\ "p,c,m"\fP). +.TP +\fB\(hyl \fR{ \fIlevel \fR| \fIname \fR}, \fB--severity \fR{ \fIlevel \fR| \fIname \fR} +Check only policy rules with severity greater than or equal to +the given level. The level may be specified as a number or as a name. +Severity names are defined as follows: +.nf +.ta 0.5iL +1.5iR + Low 33 + Medium 66 + High 100 +.fi +Mutually exclusive with (\fB\(hyR\fP). +.DT +.TP +.BI \(hyR " rule\fR, " --rule-name " rule +Check only the specified policy rule. Mutually exclusive with +(\fB\(hyl\fP). +.TP +.BI \(hyx " section\fR, " --section " section +Only check the rules in the specified section of the policy file. For +\fITripwire 2.4\fR, \fR\f(CWFS\fP is the only meaningful +argument for this flag. +.TP +.BR \(hyM ", " --email-report +Specifies that reports be emailed to the recipient(s) designated in the +policy file. +.TP +.BI \(hyt " level\fR, " --email-report-level " level +Specifies the detail level of email reports, overriding the +EMAILREPORTLEVEL variable in the configuration file. \fIlevel\fR must +be a number from 0\ to\ 4. +Valid only with (\fB\(hyM\fP). +.TP +.RI "[ " object1 " [ " object2... " ]]" +List of files and directories that should be integrity checked. +Default is all files. If files are specified for checking, the +\fB--severity\fR and \fB--rule-name\fR options will be ignored. +.\" +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Database Update mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m u --update +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-d \fIdatabase\fP --dbfile \fIdatabase\fP +-r \fIreport\fP --twrfile \fIreport\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-V \fIeditor\fP --visual \fIeditor\fP +-a --accept-all +-Z \fR{ low | high }\fP --secure-mode \fR{ low | high }\fP +.TE +.RE +.TP +.BR "\(hym u" ", " --update +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile +Use the specified policy file. +.TP +.BI \(hyd " database\fR, " --dbfile " database" +Update the specified database file. +.TP +.BI \(hyr " report\fR, " --twrfile " report" +Read the specified report file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file to read the configuration +and policy files. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to read the database +file and report file, and to re-write the database file. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specifies passphrase to be used with local key to +sign the database. +.TP +.BI \(hyV " editor\fR, " --visual " editor" +Use the specified editor to edit the update ballot boxes. Mutually +exclusive with (\fB\(hya\fP). +.TP +.BR \(hya ", " --accept-all +Specifies that all the entries in the report file are updated +without prompting. Mutually exclusive with (\fB\(hyV\fP). +.TP +\fB\(hyZ \fR{ low | high \fR}, \fB--secure-mode \fR{ low | high \fR} +Specifies the security level, which affects how certain conditions are +handled when inconsistent information is found between the report file +and the current database: +.sp +High: In \fBhigh\fP security mode, if a file does not match the +properties in the report file, Tripwire reports the differences as +warnings, and exits without changing the database. +.sp +Low: In \fBlow\fP security mode, inconsistencies +are reported as warnings, +but the changes are still made to the database. +.\" +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Policy Update mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m p --update-policy +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-d \fIdatabase\fP --dbfile \fIdatabase\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +-Z \fR{ low | high }\fP --secure-mode \fR{ low | high }\fP +.TE +.I policyfile.txt +.RE +.TP +.BR "\(hym p" ", " --update-policy +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile +Write the specified policy file. +.TP +.BI \(hyd " database\fR, " --dbfile " database" +Use the specified database file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file to read the configuration +file, and read and write the policy file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to read and write the database +file. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specifies passphrase to be used with local key to +sign the database. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specifies passphrase to be used with site key to sign +the new policy file. +.TP +\fB\(hyZ \fR{ low | high \fR}, \fB--secure-mode \fR{ low | high \fR} +Specifies the security level, which affects how certain conditions are +handled when the existing filesystem does not match the database +information. Since the database produced at the end of a policy update +becomes the baseline for future integrity checks, this +consistency-checking ensures that no substantive filesystem changes +have occurred since the last integrity check. +.sp +High: In \fBhigh\fP security mode, if a file on the filesystem does +not match the properties in the database file, Tripwire reports the +differences as warnings, and exits without changing the database or the +policy file. +.sp +Low: In \fBlow\fP security mode, inconsistencies are reported as +warnings, but the changes are still made to the database and policy +file. +.if \n(.t<700 .bp +.TP +.I policyfile.txt +Specifies the text policy file that will become the new policy file. +.\" +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Test mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m t --test +-e \fIuser@domain.com\fP --email \fIuser@domain.com\fP +.TE +.RE +.TP +.BR "\(hym t" ", " --test +Mode selector. +.TP +.BI \(hye " user@domain.com\fR, " --email " user@domain.com" +Use the specified email address. This parameter must +be supplied when test mode is used. Only one address +may be specified. +.SH VERSION INFORMATION +This man page describes +.B tripwire +version 2.4 +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR twadmin (8), +.BR twprint (8), +.BR siggen (8), +.BR twconfig (4), +.BR twpolicy (4), +.BR twfiles (5) +.PP +.IR "The Design and Implementation of Tripwire: A \s-1UNIX\s0 File Integrity Checker" +by Gene Kim and Eugene Spafford. Purdue Technical Report CSD-TR-93-071. diff --git a/man/man8/twadmin.8 b/man/man8/twadmin.8 new file mode 100644 index 0000000..034c188 --- /dev/null +++ b/man/man8/twadmin.8 @@ -0,0 +1,558 @@ +'\" t +.\" Do not move or remove previous line. +.\" Used by some man commands to know that tbl should be used. +.\" +.\" Macro added by TSS. +.\" The command mode descriptions run together visually, so +.\" macro Hr draws a horizontal rule to give some separation +.\" between modes. Register Vs dithers the amount of vertical +.\" space before the rule, in lines. +.nr Vs 1 +.de Hr +.ne \\n(Vs+2 +.sp \\n(Vsli +.nr Oi \\n(.i +.in 0 +\\l'\\n(.lu' +.in \\n(.iu +.. +.ad l +.TH TWADMIN 8 "1 July 2000" +.SH NAME +twadmin \- Tripwire administrative and utility tool +.SH SYNOPSIS +.B twadmin +.RB "{ " "-m F" " | " "--create-cfgfile" " } " +.I " options... " +.if n .br +.if n .ti +.5i +.I "configfile.txt" +.br +.B twadmin +.RB "{ " "-m f" " | " "--print-cfgfile" " } " +.RI "[ " options... " ]" +.br +.B twadmin +.RB "{ " "-m P" " | " "--create-polfile" " } " +.RI "[ " options... " ] " +.if n .br +.if n .ti +.5i +.I "policyfile.txt" +.br +.B twadmin +.RB "{ " "-m p" " | " "--print-polfile" " } " +.RI "[ " options... " ]" +.br +.B twadmin +.RB "{ " "-m R" " | " "--remove-encryption" " } " +.RI "[ " options... " ] " +.if n .br +.if n .ti +.5i +.IR file1 " [ " file2... " ]" +.br +.B twadmin +.RB "{ " "-m E" " | " "--encrypt" " } " +.RI "[ " options... " ] " +.if n .br +.if n .ti +.5i +.IR file1 " [ " file2... " ]" +.br +.B twadmin +.RB "{ " "-m e" " | " "--examine" " } " +.RI "[ " options... " ] " +.if n .br +.if n .ti +.5i +.IR file1 " [ " file2... " ]" +.br +.B twadmin +.RB "{ " "-m G" " | " "--generate-keys" " } " +.I options... +.br +.B twadmin +.RB "{ " "-m C" " | " "--change-passphrases" " } " +.I options... +.br +.SH DESCRIPTION +.PP +The \fBtwadmin\fR utility is used to perform certain administrative +functions related to \fITripwire\fR files and configuration options. +Specifically, \fBtwadmin\fR allows encoding, decoding, +signing, and verification of +\fITripwire\fR files, and provides a means to generate and change +local and site keys. +.\" ***************************************** +.SS Creating a configuration file (--create-cfgfile) +This command mode designates an existing text file as the new +configuration file for \fITripwire\fR. +The plain text configuration +file must be specified on the command line. +Using the site key, the new configuration file +is encoded and saved. +.\" ***************************************** +.SS Printing a configuration file (--print-cfgfile) +This command mode prints the specified encoded and signed +configuration file in clear-text form to standard output. +.\" ***************************************** +.SS Replacing a policy file (--create-polfile) +This command mode designates an existing text file as the new +policy file for \fITripwire\fR. +The plain text policy file must be specified on the +command line. +Using the site key, the new policy file is encoded and saved. +.\" ***************************************** +.SS Printing a policy file (--print-polfile) +This command mode prints the +specified encoded and signed policy file +in clear-text form to standard output. +.\" ***************************************** +.SS Removing encryption from a file (--remove-encryption) +This command mode allows the user to remove signing from signed +configuration, policy, database, or report files. Multiple +files may be specified on the command line. The +user will need to enter the appropriate local or site keyfile, +or both if a combination of files is to be verified. Even with the +cryptographic signing removed, these files will be in a binary encoded +(non-human-readable) form. +.\" ***************************************** +.SS Encrypting a file (--encrypt) +This command mode allows the user to sign +configuration, policy, database files, or reports. +Multiple files may be specified on the command line. +The files will be signed using either the site or local key, +as appropriate for the type of file. +To automate the process, the passphrase for the key +files can be included on the command line. +.\" ***************************************** +.hy 0 +.SS "Examining the signing status of a file (\(hy\(hyexamine)" +.hy 1 +This command allows the user to examine the listed files +and print a report of their signing status. This report +displays the filename, file type, whether or not a file is +signed, and what key (if any) is used to sign it. +.\" ***************************************** +.SS Generating keys (--generate-keys) +This command mode generates site and/or local key files with +names specified by the user. +.\" ***************************************** +.SS Changing passphrases (--change-passphrases) +This command reencrypts the private part of the +site and/or local key files using the key filenames and passphrases +specified by the user. +.\" ***************************************** +.if \n(.t<700 .bp +.SH OPTIONS +.\" ***************************************** +.SS Creating a configuration file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m F --create-cfgfile +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +-e --no-encryption +.TE +.I configfile.txt +.RE +.TP +.BR "\(hym F" ", " "--create-cfgfile" +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Specify the destination of the encoded (and optionally signed) +configuration file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file to encode and sign the new +configuration file. +Exactly one of (\fB\(hyS\fR) or (\fB\(hye\fP) must be specified. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specifies passphrase to be used with site key for +configuration file encoding and signing. +Valid only in conjunction with (\fB\(hyS\fR). +.TP +.BR \(hye ", " --no-encryption +Do not sign the configuration file being stored. +The configuration +file will still be compressed, and will not be human-readable. +Mutually exclusive with (\fB\(hyQ\fR) and (\fB\(hyS\fR). +.TP +.I configfile.txt +Specifies the text configuration file that will become +the new configuration file. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Printing a configuration file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m f --print-cfgfile +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +.TE +.RE +.TP +.BR "\(hym f" ", " "--print-cfgfile" +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Print the specified configuration file. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Creating a policy file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m P --create-polfile +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +-e --no-encryption +.TE +.I policyfile.txt +.RE +.TP +.BR "\(hym P" ", " --create-polfile +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile" +Specify the destination of the encoded (and optionally signed) policy +file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file. Mutually exclusive with (\fB\(hye\fR). +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specifies passphrase to be used with site key for policy signing. +Mutually exclusive with (\fB\(hye\fR). +.TP +.BR \(hye ", " --no-encryption +Do not sign the policy file being stored. The policy +file will still be compressed, and will not be human-readable. +Mutually exclusive with (\fB\(hyQ\fR) and (\fB\(hyS\fR). +.TP +.I policyfile.txt +Specifies the text policy file that will become the new +policy file. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Printing a policy file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m p --print-polfile +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-p \fIpolfile\fP --polfile \fIpolfile\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +.TE +.RE +.TP +.BR "\(hym p" ", " --print-polfile +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyp " polfile\fR, " --polfile " polfile" +Print the specified policy file. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Use the specified site key file. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Removing encryption from a file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m R --remove-encryption +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +.TE +.IR "file1" " [ " "file2..." " ]" +.RE +.TP +.BR "\(hym R" ", " --remove-encryption +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Specify the local keyfile to use to verify database files and reports. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Specify the site keyfile to use to verify configuration +and policy files. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specify the passphrase to use when verifying with the +old local keyfile. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specify the passphrase to use when verifying with the +old site keyfile. +.TP +.IR file1 " [ " file2... " ]" +List of files from which signing is to be removed. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Encrypting a file: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m E --encrypt +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +.TE +.IR "file1" " [ " "file2..." " ]" +.RE +.TP +.BR "\(hym E" ", " --encrypt +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Specify the local keyfile to use to sign database +files and reports. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Specify the site keyfile to use to sign configuration +and policy files. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specify the passphrase to use when signing with the +local keyfile. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specify the passphrase to use when signing with the +site keyfile. +.TP +.IR file1 " [ " file2... " ]" +List of files to sign using the new key(s). +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS "Examining the encryption status of a file:" +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m e --examine +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +.TE +.IR file1 " [ " file2... " ]" +.RE +.TP +.BR "\(hym e" ", " --examine +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Specifies the key to use as a local key. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Specifies the key to use as a site key. +.TP +.IR file1 " [ " file2... " ]" +List of files to examine. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Generating keys: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m G --generate-keys +-v --verbose +-s --silent\fR,\fP --quiet +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP +.TE +.RE +.TP +.BR "\(hym G" ", " --generate-keys +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Generate the local key into the specified file. At least one of +(\fB\(hyL\fR) or (\fB\(hyS\fR) must be specified. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Generate the site key into the specified file. At least one of +(\fB\(hyS\fR) or (\fB\(hyL\fR) must be specified. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specify local passphrase to be used when generating +the local key. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specify site passphrase to be used when generating +the site key. +.\" ***************************************** +.Hr +.if \n(.t<700 .bp +.SS Changing passphrases: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m C --change-passphrases +-v --verbose +-s --silent\fR,\fP --quiet +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-S \fIsitekey\fP --site-keyfile \fIsitekey\fP +-P \fIpassphrase\fP --local-passphrase \fIpassphrase\fP +-Q \fIpassphrase\fP --site-passphrase \fIpassphrase\fP + --local-passphrase-old \fIpassphraseOld\fP + --site-passphrase-old \fIpassphraseOld\fP +.TE +.RE +.TP +.BR "\(hym C" ", " --change-passphrases +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Change passphrase used to encrypt the private key in the specified localkey +file. At least one of (\fB\(hyL\fR) or (\fB\(hyS\fR) must be specified. +.TP +.BI \(hyS " sitekey\fR, " --site-keyfile " sitekey" +Change passphrase used to encrypt the private key in the specified sitekey +file. At least one of (\fB\(hyL\fR) or (\fB\(hyS\fR) must be specified. +.TP +.BI \(hyP " passphrase\fR, " --local-passphrase " passphrase" +Specify passphrase used to encrypt the private key in the specified localkey +file. +.TP +.BI \(hyQ " passphrase\fR, " --site-passphrase " passphrase" +Specify passphrase used to encrypt the private key in the specified sitekey +file. +.TP +.BI --local-passphrase-old " passphraseOld" +Specify passphrase used to decrypt the private key in the specified localkey +file. +.TP +.BI --site-passphrase-old " passphraseOld" +Specify passphrase used to decrypt the private key in the specified sitekey +file. +.\" ***************************************** +.SH VERSION INFORMATION +This man page describes +.B twadmin +version 2.4. +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twprint (8), +.BR siggen (8), +.BR twconfig (4), +.BR twpolicy (4), +.BR twfiles (5) diff --git a/man/man8/twintro.8 b/man/man8/twintro.8 new file mode 100644 index 0000000..9279cf2 --- /dev/null +++ b/man/man8/twintro.8 @@ -0,0 +1,112 @@ +.\" Macros added by addw@phcomp.co.uk for those systems where the an +.\" troff macro package doesn't know about .Ps & .Pe. +.\" Note it is assumed that CW is a constant width font. +.\" Ps - Start display text +.de Ps +.nf +.in +0.5i +.ft CW +.. +.\" Pe - end of display text +.de Pe +.fi +.in -0.5i +.ft 1 +.. +.\" +.nh +.ad l +.TH TWINTRO 8 "1 July 2000" +.SH NAME +twintro \- introduction to \fITripwire\fP software +.SH DESCRIPTION +.PP +\fITripwire 2.4\fP is a file integrity assessment product for Linux networks. Rather than preventing an intruder or virus +from attacking system files, \fITripwire\fP detects intrusions when +they do occur. By comparing system files and directories against a +previously stored "baseline" database, \fITripwire\fP finds any +additions, deletions, or changes to specified properties. This allows +the system administrator to determine the extent of the problem and +begin necessary damage control. +.PP +After \fITripwire\fP is installed on a system, the following four +commands are used: +.RS 0.3i +.ie n .HP +.el .PP +.BR tripwire (8) +is used for most of the basic operations of the +software. This includes creation of the \fITripwire\fP database, and +checking the integrity of the filesystem against that database. +.ie n .HP +.el .PP +.BR twadmin (8) +is used to create, encode, and sign \fITripwire\fP policy, +configuration, and key files, and +for various administrative functions. +.ie n .HP +.el .PP +.BR twprint (8) +prints \fITripwire\fP database and report files in +a plain text format. +.ie n .HP +.el .PP +.BR siggen (8) +is a file utility that displays hash +values for files. +.RE +.PP +In addition to the command references listed above, the following three +man pages provide information on important components of the +\fITripwire\fP package. +.RS 0.3i +.ie n .HP +.el .PP +.BR twfiles (5) +provides an overview of the various files created and +used by \fITripwire\fP, including default locations and settings. +.ie n .HP +.el .PP +.BR twconfig (4) +explains the configuration file, which is used to set +system-specific information that affects \fITripwire\fP operation. +.ie n .HP +.el .PP +.BR twpolicy (4) +explains the policy file, which specifies the files +and directories \fITripwire\fP should check, and how they should be +scanned. +.RE +.PP +Using the +.B \(hy\(hyhelp +flag with any \fITripwire\fP command +(e.g.\ \fBtripwire\ \(hy\(hyhelp\fP) will print a short summary of the +command modes for that command. If a mode selector is also specified +(e.g.\ \fBtripwire\ \(hy\(hycheck\ \(hy\(hyhelp\fP), a mode\(hyspecific +usage message will be displayed. Using the \fBall\fP argument with the +\fB--help\fP flag (e.g.\ \fBtripwire\ \(hy\(hyhelp\ all\fP) will print +detailed usage messages for all modes of the specified command. +.SH VERSION INFORMATION +This man page describes +.IR "Tripwire 2.4" "." +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR tripwire (8), +.BR twadmin (8), +.BR twprint (8), +.BR siggen (8), +.BR twconfig (4), +.BR twpolicy (4), +.BR twfiles (5) +.PP +.IR "The Design and Implementation of Tripwire: A \s-1UNIX\s0 File Integrity Checker" by Gene Kim and Eugene Spafford. Purdue Technical Report CSD-TR-93-071. diff --git a/man/man8/twprint.8 b/man/man8/twprint.8 new file mode 100644 index 0000000..1dc449e --- /dev/null +++ b/man/man8/twprint.8 @@ -0,0 +1,148 @@ +'\" t +.\" Do not move or remove previous line. +.\" Used by some man commands to know that tbl should be used. +.ad l +.TH TWPRINT 8 "1 July 2000" +.nh +.SH NAME +twprint \- Tripwire database and report printer +.SH SYNOPSIS +.B twprint +.RB "{ " "-m r" " | " "--print-report" " } " +.RI "[ " options... " ]" +.br +.B twprint +.RB "{ " "-m d" " | " "--print-dbfile" " } " +.RI "[ " options... " ]" +.if n .br +.if n .ti +.5i +.RI " [ " "object1" " [ " "object2..." " ]]" +.SH DESCRIPTION +.PP +Prints \fITripwire\fR database and report files in clear text format. +.SS Report Printing mode +.PP +In Report Printing mode, \fBtwprint\fR verifies and displays the +contents of a \fITripwire\fR report file (\fI.twr\fR). If no report is +specified on the command line, +the report specified in the +\f(CWREPORTFILE\fR +variable in the configuration file will be used. By default, +this value includes the date and time to the nearest second. Because +this value is constantly changing, \fBtwprint\fR may not be able to +find the correct report file. For this reason, the (\fB\(hyr\fR or +\fB--twrfile\fR) flag should be used with the desired report name to +print a specific report. +.SS Database Printing mode +.PP +This option is used to print a \fITripwire\fR database file in +human-readable (clear text) form. In Database Printing mode, +\fBtwprint\fR verifies and +prints the contents of a specified database to \fIstdout\fR. If no +database file is specified +on the command line, the default database specified by the +\f(CWDBFILE\fR +variable in the configuration file is used. +.SH OPTIONS +.\" ***************************************** +.SS Report printing mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m r --print-report +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-r \fIreport\fP --twrfile \fIreport\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +-t \fR{ 0|1|2|3|4 }\fP --report-level \fR{ 0|1|2|3|4 }\fP +.TE +.RE +.TP +.BR "\(hym r" ", " --print-report +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyr " report\fR, " --twrfile " report" +Print the specified report file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to perform verification +with reports which are signed. +.TP +.BI \(hyt " level\fR, " --report-level " level +Specifies the detail level of the printed report, overriding the +\f(CWREPORTLEVEL\fP variable in the configuration +file. \fIlevel\fR must be a number from 0\ to\ 4. +.\" ***************************************** +.SS Database printing mode: +.RS 0.4i +.TS +; +lbw(1.2i) lb. +-m d --print-dbfile +-v --verbose +-s --silent\fR,\fP --quiet +-c \fIcfgfile\fP --cfgfile \fIcfgfile\fP +-d \fIdatabase\fP --dbfile \fIdatabase\fP +-L \fIlocalkey\fP --local-keyfile \fIlocalkey\fP +.TE +.RI "[ " "object1" " [ " "object2..." " ]]" +.RE +.TP +.BR "\(hym d" ", " --print-dbfile +Mode selector. +.TP +.BR \(hyv ", " --verbose +Verbose output mode. Mutually exclusive with (\fB\(hys\fR). +.TP +.BR \(hys ", " --silent ", " --quiet +Silent output mode. Mutually exclusive with (\fB\(hyv\fR). +.TP +.BI \(hyc " cfgfile\fR, " --cfgfile " cfgfile" +Use the specified configuration file. +.TP +.BI \(hyd " database\fR, " --dbfile " database" +Print the specified database file. +.TP +.BI \(hyL " localkey\fR, " --local-keyfile " localkey" +Use the specified local key file to read the database. +.TP +.RI "[ " "object1" " [ " "object2..." " ]]" +List of filesystem objects in the database to print. If no +objects are specified, every object in the database will +be printed. The format for a list of objects is: +.if n .I "section: objname objname... section: objname..." +.if t .br +.if t .I "section: objectname objectname... section: objectname..." +.SH VERSION INFORMATION +This man page describes +.B twprint +version 2.4. +.SH AUTHORS +Tripwire, Inc. +.SH COPYING PERMISSIONS +Permission is granted to make and distribute verbatim copies of this man page provided the copyright notice and this permission notice are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this man page under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this man page into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by Tripwire, Inc. +.PP +Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, Inc. in the United States and other countries. All rights reserved. +.SH SEE ALSO +.BR twintro (8), +.BR tripwire (8), +.BR twadmin (8), +.BR siggen (8), +.BR twconfig (4), +.BR twpolicy (4), +.BR twfiles (5) diff --git a/missing b/missing new file mode 100755 index 0000000..3aef1fb --- /dev/null +++ b/missing @@ -0,0 +1,283 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.3 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version > /dev/null 2>&1); then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar ${1+"$@"} && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar ${1+"$@"} && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000..0ea4d23 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1 2001/02/18 15:08:31 pherman Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/policy/policy_generator_readme.txt b/policy/policy_generator_readme.txt new file mode 100644 index 0000000..eb8e9ff --- /dev/null +++ b/policy/policy_generator_readme.txt @@ -0,0 +1,15 @@ +* Tripwire 2.4.2.2 Policy Generator README + +This readme is a quick guide on something introduced in this version +of Tripwire: the Policy Generator. The idea behind is to generate a +custom file fitting your system. + +It has so far been tested on Debian Wheezy and CentOS 5.7/6.0, your +mileage may vary. + +This is not part of the standard install so you will have to do this +manually for now if you want to use it. + +This is also provided as-is but if you happen to find out bugs, have +improvement suggestions or patches, send them to: tripwire@frlinux.net + diff --git a/policy/policyguide.txt b/policy/policyguide.txt new file mode 100644 index 0000000..09bf2e9 --- /dev/null +++ b/policy/policyguide.txt @@ -0,0 +1,215 @@ +# Demonstration policy file for Linux and Unix + +# Tripwire, Inc. is not responsible for the accuracy +# of this file or its relevance to your system. This file is provided +# only as a starting point and example. We highly encourage you to +# use this file to create a new policy file that suits the security needs +# and eccentricities of your own machine. + +# This policy file contains individually valid rules to demonstrate all +# current language features created for the Tripwire 2.3 release. + + +# This is a comment. Tripwire treats all text following a "#" as a comment. + +/etc/hosts -> +pinugs; # This is a very basic rule. + # Tripwire will alert you if any of + # the specified properties for + # the file /etc/hosts are modified. + +!/etc/init.d ; # The "!" indicates a stop point. + # The directory /etc/init.d will + # not be scanned. + +!/etc/netmasks ; # Stop point on a file. Tripwire + # will not scan /etc/netmasks + +"/home/fred/big file" -> +pingus; # Double quotes can be used to + # protect special cases such as + # filenames with spaces and escaped + # characters. +"/home/emu/o\163trich" -> +s; # Escaped octal character +"/home/emu/\x64odo" -> +m; # Escaped hex character +"/home/emu/blue\'jay" -> +c; # Escaped character + + +# The following rules demonstrate a scan using each of the individual +# property selection masks. + +/etc/passwd -> +a; # Access timestamp +/etc/passwd -> +b; # Number of blocks +/etc/passwd -> +c; # Inode timestamp (create/modify) +/etc/passwd -> +d; # Inode storage disk device number +/etc/passwd -> +g; # File owner's group ID +/etc/passwd -> +i; # Inode number +/etc/passwd -> +m; # Modification timestamp +/etc/passwd -> +n; # inode reference count +/etc/passwd -> +p; # Permissions and file mode bits +/etc/passwd -> +r; # Device Number +/etc/passwd -> +s; # File size +/etc/passwd -> +t; # File Type +/etc/passwd -> +u; # File owner's user ID +/etc/passwd -> +l; # File is increasing in size +/etc/passwd -> +C; # CRC-32 hash value +/etc/passwd -> +M; # MD5 hash value +/etc/passwd -> +S; # SHA hash value +/etc/passwd -> +H; # Haval signature value + +# Rules can be given specific attributes which influence how tripwire +# behaves either while scanning or when it detects an infraction. + +/etc -> +ug (recurse=false); # The recurse attribute controls + # recursive scanning of the + # contents of a directory. In this + # case, recurse is set to false, so + # tripwire will scan the /etc + # directory but not its contents. + +/etc -> +ug (rulename=software); # Setting a rulename allows you to + # associate a rule or set of rules + # with a specific name. This can + # help you to sort data in your + # Tripwire reports. For this rule, + # any infraction in the /etc + # directory will appear as part of + # the "software" section of the + # report. + +/etc -> +ug (emailto=admin@domain.com); # The emailto attribute will cause + # Tripwire to send email to a + # specified user if the indicated + # rule is broken. In this case, + # admin@domain.com will receive a + # tripwire report if someone + # changes the user or group id on + # any file in the /etc directory. + +/etc -> +ug (emailto="admin@domain.com webmaster@domain.com") + # you can use quotes to email to + # more than one person. + + +/etc -> +ug (severity=50); # You can set the severity of a + # rule so that you can quickly scan + # through a report to find the + # most critical changes. + +# Setting variables is a good way to easily change the parameters for +# several rules at once. + +param1 = +SMCH; # Set variable param1. +dir1 = /etc/inet; # Set variable dir1 +DIR1 = /etc/init.d; # Variables are case sensitive + +$(dir1) -> +tbamc; # Rule using directory substitution + # or "left Hand substitution" + +/etc/inet -> $(param1); # Rule using selection mask + # substitution or "Right Hand + # substitution". + +$(DIR1) -> $(param1); # It is also possible to do a + # double substitution. + +# Tripwire also provides several predefined variables. + +/etc/httpd/weblog -> $(Growing); # The Growing variable is intended + # for files that should only grow, + # such as the web log in this + # example. Growing uses the + # following masks: +pinugtdl + +/etc/passwd -> $(IgnoreNone); # IgnoreNone should be used on + # critical files such as passwd. + # It checks all file attributes: + # +pinusgamctdbCMSH + +/home/fred/mytextfile -> $(IgnoreAll); # If you want to track a file's + # presence or absence but do + # not care about its properties, + # use IgnoreAll. IgnoreAll ignores + # all attributes: pinusglamctdbCMSH + +/usr/httpd/index.html -> $(ReadOnly); # ReadOnly is good for files that + # are widely available but are + # intended to be read-only. + # Attributes: +pinugsmtdbCM + +/home/fred -> $(Dynamic); # Dynamic is good for monitoring + # user directories and files that + # tend to be dynamic in behavior. + # Attributes: +pinugtd + +/dev/null -> $(Device); # Device is appropriate for checking + # system devices and any other + # files that may be important, but + # should be relatively static and + # accessed often: +pugs + +# Directives are useful if you want to use one policy across your network +# servers, but also require special rules for each machine. + +@@ifhost salmon # The following rule will only run +/etc -> +abcdgimnpstul; # will only run if the server name + # is salmon. +@@else +/bin -> +abcdgimnpstul; # All other servers will run this +@@endif # rule. + +# Directives can also be nested: + +@@ifhost crayfish +/etc/passwd -> $(Growing); # Will only check /etc/passwd if + # your hostname is crayfish. +@@else # Otherwise it will check if your + @@ifhost salmon # hostname is salmon. If so it + /etc/passwd -> $(IgnoreAll); # will ignore passwd. + @@endif # If your server has any other name + /etc/passwd -> $(IgnoreNone); # then passwd is fully examined. +@@endif + +# The following examples demonstrate more complicated uses of Tripwire that +# are more likely to be seen in a real environment. + +# Trailing rules: These are typical of the rule format used in most of +# this file. This is by far the most common usage. + +/home/fred/specialfile -> asd (emailto=fred@domain.com, Rulename=special, severity=50); +/home/fred/generalworkfile -> bm (Rulename=work, severity=60); +/home/fred/myreport -> CSH (Rulename=report, severity=75); +/home/fred/mypresentation.data -> Mpi (Rulename=urgent, severity=90); + +# Preceding rules: These are extremely helpful if you wish to apply a rule +# to a large group of files or directories. + +(Rulename=standard, severity=30) +{ + /home/fred -> lgu; + /home/jane -> CHM; + /home/project/report.file -> $(Growing); +} + +#============================================================================= +# +# Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, +# Inc. All rights reserved. +# +# Linux is a registered trademark of Linus Torvalds. +# +# UNIX is a registered trademark of The Open Group. +# +#============================================================================= +# +# Permission is granted to make and distribute verbatim copies of this document +# provided the copyright notice and this permission notice are preserved on all +# copies. +# +# Permission is granted to copy and distribute modified versions of this +# document under the conditions for verbatim copying, provided that the entire +# resulting derived work is distributed under the terms of a permission notice +# identical to this one. +# +# Permission is granted to copy and distribute translations of this document +# into another language, under the above conditions for modified versions, +# except that this permission notice may be stated in a translation approved by +# Tripwire, Inc. diff --git a/policy/templates/create_twpol.sh b/policy/templates/create_twpol.sh new file mode 100755 index 0000000..79ce06c --- /dev/null +++ b/policy/templates/create_twpol.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# +# 2011-11-21 - v0.2 : added more checks +# 2011-09-21 - v0.1 : first attempt to create a custom file +# FRLinux - tripwire@frlinux.net +# + +echo " " +echo "Please run this as ROOT, failing to do so might prevent from" +echo "indexing all directories." +echo " " + +BASECONFIG="." +POL="$BASECONFIG/../twpol.txt" +POL_HEADER="$BASECONFIG/twpol-header.txt" +POL_FOOTER="$BASECONFIG/twpol-footer.txt" + +echo "# `date` " > $POL +echo "#" >> $POL +echo "# New Policy file format - FRLinux tripwire@frlinux.net" >> $POL +echo "# This is experimental, check the readme before using this." >> $POL +echo "#" >> $POL +cat $POL_HEADER >> $POL + +echo "" >> $POL +echo "# File System and Disk Administration Programs." >> $POL +echo "" >> $POL + +if [ `uname -i` = "x86_64" ]; then +dir64="/lib64" +else +dir64="" +fi +for dir in /bin /sbin /lib /etc $dir64 +do + echo "(" >> $POL + echo " rulename = \"files in $dir\"," >> $POL + echo " severity = \$(SIG_HI)" >> $POL + echo ")" >> $POL + echo "{" >> $POL + find $dir -type f -printf " %p -> \$(SEC_CRIT);\n" >> $POL + echo "}" >> $POL + echo "" >> $POL +done + +for type in root sys +do + cat $type.tpl >> $POL +done + +cat $POL_FOOTER >> $POL + +echo " " +echo "Copy this file in $TRIPWIRE_INSTALL/etc/twpol.txt" +echo "then execute: tripwire --update-policy twpol.txt" +echo " " +echo "Done." + diff --git a/policy/templates/root.tpl b/policy/templates/root.tpl new file mode 100644 index 0000000..c1c85f0 --- /dev/null +++ b/policy/templates/root.tpl @@ -0,0 +1,33 @@ +# These files change the behavior of the root account +( + rulename = "Root config files", + severity = 100 +) +{ + /root -> $(SEC_CRIT) ; # Catch all additions to /root + /root/.Xresources -> $(SEC_CONFIG) ; + /root/.bashrc -> $(SEC_CONFIG) ; + /root/.bash_profile -> $(SEC_CONFIG) ; + /root/.bash_logout -> $(SEC_CONFIG) ; + /root/.cshrc -> $(SEC_CONFIG) ; + /root/.tcshrc -> $(SEC_CONFIG) ; + #/root/Mail -> $(SEC_CONFIG) ; + #/root/mail -> $(SEC_CONFIG) ; + #/root/.amandahosts -> $(SEC_CONFIG) ; + #/root/.addressbook.lu -> $(SEC_CONFIG) ; + #/root/.addressbook -> $(SEC_CONFIG) ; + /root/.bash_history -> $(SEC_CONFIG) ; + #/root/.elm -> $(SEC_CONFIG) ; + /root/.esd_auth -> $(SEC_CONFIG) ; + #/root/.gnome_private -> $(SEC_CONFIG) ; + #/root/.gnome-desktop -> $(SEC_CONFIG) ; + /root/.gnome -> $(SEC_CONFIG) ; + /root/.ICEauthority -> $(SEC_CONFIG) ; + #/root/.mc -> $(SEC_CONFIG) ; + #/root/.pinerc -> $(SEC_CONFIG) ; + #/root/.sawfish -> $(SEC_CONFIG) ; + /root/.Xauthority -> $(SEC_CONFIG) -i ; # Changes Inode number on login + #/root/.xauth -> $(SEC_CONFIG) ; + #/root/.xsession-errors -> $(SEC_CONFIG) ; +} + diff --git a/policy/templates/sys.tpl b/policy/templates/sys.tpl new file mode 100644 index 0000000..e82b57c --- /dev/null +++ b/policy/templates/sys.tpl @@ -0,0 +1,47 @@ +( + rulename = "Critical devices", + severity = $(SIG_HI), + recurse = false +) +{ + /dev/kmem -> $(Device) ; + /dev/mem -> $(Device) ; + /dev/null -> $(Device) ; + /dev/zero -> $(Device) ; + /proc/devices -> $(Device) ; + /proc/net -> $(Device) ; + /proc/sys -> $(Device) ; + /proc/cpuinfo -> $(Device) ; + /proc/modules -> $(Device) ; + /proc/mounts -> $(Device) ; + /proc/dma -> $(Device) ; + /proc/filesystems -> $(Device) ; + /proc/pci -> $(Device) ; + /proc/interrupts -> $(Device) ; + /proc/driver/rtc -> $(Device) ; + /proc/ioports -> $(Device) ; + /proc/scsi -> $(Device) ; + /proc/kcore -> $(Device) ; + /proc/self -> $(Device) ; + /proc/kmsg -> $(Device) ; + /proc/stat -> $(Device) ; + /proc/ksyms -> $(Device) ; + /proc/loadavg -> $(Device) ; + /proc/uptime -> $(Device) ; + /proc/locks -> $(Device) ; + /proc/version -> $(Device) ; + /proc/mdstat -> $(Device) ; + /proc/meminfo -> $(Device) ; + /proc/cmdline -> $(Device) ; + /proc/misc -> $(Device) ; + /sys/block -> $(Device) ; + /sys/bus -> $(Device) ; + /sys/class -> $(Device) ; + /sys/devices -> $(Device) ; + /sys/firmware -> $(Device) ; + /sys/fs -> $(Device) ; + /sys/kernel -> $(Device) ; + /sys/module -> $(Device) ; + /sys/power -> $(Device) ; +} + diff --git a/policy/templates/twpol-footer.txt b/policy/templates/twpol-footer.txt new file mode 100644 index 0000000..9e95b5c --- /dev/null +++ b/policy/templates/twpol-footer.txt @@ -0,0 +1,28 @@ + +# license: +#============================================================================= +# +# Copyright 2011 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, +# Inc. in the United States and other countries. All rights reserved. +# +# Linux is a registered trademark of Linus Torvalds. +# +# UNIX is a registered trademark of The Open Group. +# +#============================================================================= +# +# Permission is granted to make and distribute verbatim copies of this document +# provided the copyright notice and this permission notice are preserved on all +# copies. +# +# Permission is granted to copy and distribute modified versions of this +# document under the conditions for verbatim copying, provided that the entire +# resulting derived work is distributed under the terms of a permission notice +# identical to this one. +# +# Permission is granted to copy and distribute translations of this document +# into another language, under the above conditions for modified versions, +# except that this permission notice may be stated in a translation approved by +# Tripwire, Inc. +# +# DCM diff --git a/policy/templates/twpol-header.txt b/policy/templates/twpol-header.txt new file mode 100644 index 0000000..50bf9df --- /dev/null +++ b/policy/templates/twpol-header.txt @@ -0,0 +1,90 @@ +# identifier: tripwire IDS policy input file +# host: Fedora Core release 1 (Yarrow) +# version: 2.4.3 +# maintainer: FRLinux +# validator: unvalidated +# date: Wed Sep 21 13:50:21 UTC 2011 + +# description: +# This is an example Tripwire Policy input file. It is intended as the +# starting point to creating your own custom Tripwire Policy. Referring +# to it, as well as the Tripwire Policy Guide, should give you enough +# information to make a good custom Tripwire Policy that better fits +# your configuration and security needs. This text version will be used +# by tripwire as input to create a proprietary type of file called a +# Tripwire Policy file, which will then be signed for further security. +# It is recommended that once you complete the creation of the Policy +# file, you move this plaintext version to a secure location (possibly +# on removable media) or encrypt the file using a tool such as GPG. You +# should also do this for the Tripwire plaintext configuration file +# (twcfg.txt) once you have finished setting up the Policy. +# +# Note that this file is tuned to an "everything" install of Fedora +# Linux. If run unmodified, this file should create no errors on +# database creation, or violations on a subsequent integrity check. +# However, it is impossible for there to be one policy file for all +# machines, so this existing one errs on the side of security. Your +# Linux configuration will most likely differ from the one our policy +# file was tuned to, and will therefore require some editing of the +# default Tripwire Policy file. The example policy file is best run +# with "Loose Directory Checking" enabled. +# +# Set LOOSEDIRECTORYCHECKING=TRUE in the Tripwire Configuration file. +# +# Note - legacy entries (which are commented out) are included for +# historical reasons only, and are overdue for removal. They will +# likely disappear from future releases. +# +# The following info is only really useful for non-RPM distributions: +# +# Email support is not included and must be added to this file. Add the +# "emailto=" to the rule directive section of each rule (add a comma +# after the "severity=" line and add an "emailto=" and include the +# email addresses you want the violation reports to go to). Addresses +# are semi-colon delimited. +# +# If you installed from the Fedora RPM, a cron job has already been set +# up for you. Tripwire will perform an integrity check once every day, +# and the generated report will be emailed to root. In this case, you +# do not need to perform the steps in the previous paragraph. + +# policy: + + +# Global Variable Definitions + +@@section GLOBAL +TWROOT=/usr/sbin; +TWBIN=/usr/sbin; +TWPOL="/etc/tripwire"; +TWDB="/var/lib/tripwire"; +TWSKEY="/etc/tripwire"; +TWLKEY="/etc/tripwire"; +TWREPORT="/var/lib/tripwire/report"; +HOSTNAME=dub6041; + +@@section FS +SEC_CRIT = $(IgnoreNone)-SHa ; # Critical files that cannot change +SEC_SUID = $(IgnoreNone)-SHa ; # Binaries with the SUID or SGID flags set +SEC_BIN = $(ReadOnly) ; # Binaries that should not change +SEC_CONFIG = $(Dynamic) ; # Config files that are changed infrequently but accessed often +SEC_LOG = $(Growing) ; # Files that grow, but that should never change ownership +SEC_INVARIANT = +tpug ; # Directories that should never change permission or ownership +SIG_LOW = 33 ; # Non-critical files that are of minimal security impact +SIG_MED = 66 ; # Non-critical files that are of significant security impact +SIG_HI = 100 ; # Critical files that are significant points of vulnerability + + +# Commonly accessed directories that should remain static with regards +# to owner and group. + +( + rulename = "Invariant Directories", + severity = $(SIG_MED) +) +{ + / -> $(SEC_INVARIANT) (recurse = 0) ; + /home -> $(SEC_INVARIANT) (recurse = 0) ; + /etc -> $(SEC_INVARIANT) (recurse = 0) ; +} + diff --git a/policy/twpol-AIX.txt b/policy/twpol-AIX.txt new file mode 100644 index 0000000..7d4f37c --- /dev/null +++ b/policy/twpol-AIX.txt @@ -0,0 +1,281 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Policy file for AIX 5.X # # +# ## +############################################################################## + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# Manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL +TWDOCS=; +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + + ############################################################################## + # Predefined Variables # +############################################################################## +# +# Property Masks +# +# - ignore the following properties +# + check the following properties +# +# a access timestamp (mutually exclusive with +CMSH) +# b number of blocks allocated +# c inode creation/modification timestamp +# d ID of device on which inode resides +# g group id of owner +# i inode number +# l growing files (logfiles for example) +# m modification timestamp +# n number of links +# p permission and file mode bits +# r ID of device pointed to by inode (valid only for device objects) +# s file size +# t file type +# u user id of owner +# +# C CRC-32 hash +# H HAVAL hash +# M MD5 hash +# S SHA hash +# +############################################################################## + +Device = +pugsdr-intlbamcCMSH ; +Dynamic = +pinugtd-srlbamcCMSH ; +Growing = +pinugtdl-srbamcCMSH ; +IgnoreAll = -pinugtsdrlbamcCMSH ; +IgnoreNone = +pinugtsdrbamcCMSH-l ; +ReadOnly = +pinugtsdbmCM-rlacSH ; +Temporary = +pugt ; + +@@section FS + + ######################################## + # ## +######################################## # +# # # +# Tripwire Binaries and Data Files # # +# ## +######################################## + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", +) +{ + $(TWBIN)/siggen -> $(ReadOnly) ; + $(TWBIN)/tripwire -> $(ReadOnly) ; + $(TWBIN)/twadmin -> $(ReadOnly) ; + $(TWBIN)/twprint -> $(ReadOnly) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(Dynamic) -i ; + $(TWPOL)/tw.pol -> $(ReadOnly) -i ; + $(TWPOL)/tw.cfg -> $(ReadOnly) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(ReadOnly) ; + $(TWSKEY)/site.key -> $(ReadOnly) ; + + # don't scan the individual reports + $(TWREPORT) -> $(Dynamic) (recurse=0) ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Boot and Configuration Files # # +# ## +################################################ +( + rulename = "OS Boot and Configuration Files", +) +{ + /etc -> $(IgnoreNone) -SHa ; +} + + ################################################### + # ## +################################################### # +# # # +# Mount Points # # +# ## +################################################### +( + rulename = "Mount Points", +) +{ + / -> $(ReadOnly) ; + /usr -> $(ReadOnly) ; + /var -> $(ReadOnly) ; +} + + ################################################### + # ## +################################################### # +# # # +# Misc Top-Level Directories # # +# ## +################################################### +( + rulename = "Misc Top-Level Directories", +) +{ + /lost+found -> $(ReadOnly) ; + /hacmplocal -> $(ReadOnly) ; + /homelocal -> $(ReadOnly) ; + /opt -> $(ReadOnly) ; + !/var/adm/csd ; +} + + ################################################ + # ## +################################################ # +# # # +# System Devices # # +# ## +################################################ +( + rulename = "System Devices", +) +{ + /dev -> $(Device) ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Binaries and Libraries # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", +) +{ + /sbin -> $(ReadOnly) ; + /usr/bin -> $(ReadOnly) ; + /usr/lib -> $(ReadOnly) ; + /usr/sbin -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Root Directory and Files # # +# ## +################################################ +( + rulename = "Root Directory and Files", +) +{ + #/.dtprofile -> $(Dynamic) ; + ! /.netscape/cache ; + /.netscape/history.dat -> $(Dynamic) ; + /.sh_history -> $(Dynamic) ; + #/.Xauthority -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Temporary Directories # # +# ## +################################################ +( + rulename = "Temporary Directories", +) +{ + /tmp -> $(Temporary) ; + /var/tmp -> $(Temporary) ; +} + + ################################################ + # ## +################################################ # +# # # +# Directories to Ignore # # +# ## +################################################ +( + rulename = "Directories to Ignore", +) +{ + !/proc ; +} + + + ################################################ + # ## +################################################ # +# # # +# System and Boot Changes # # +# ## +################################################ +( + rulename = "System and Boot Changes", +) +{ + /etc/es/objrepos -> $(ReadOnly) -SHacm ; + /etc/es/objrepos/HACMPresource -> $(ReadOnly) -SHCMcm ; + /etc/lpp/diagnostics/data -> $(ReadOnly) -SHCMacm ; + /etc/ntp.drift -> $(ReadOnly) -SHiacm ; + !/etc/objrepos ; + /etc/security -> $(ReadOnly) -SHacm ; + /usr/es/adm/cluster.log -> $(ReadOnly) -SHCMsbm ; + /usr/es/sbin/cluster/etc/objrepos/active -> $(ReadOnly) -SHim ; + !/usr/etc/sbin/cluster/history ; + /usr/share/lib/objrepos -> $(ReadOnly) -m ; + /usr/lib/objrepos -> $(ReadOnly) -m ; + !/var/adm/SPlogs ; + /var/ha/log -> $(Growing) -i ; + !/var/adm ; + !/var/ct ; + + #/var/backups -> $(Dynamic) -i ; + #/var/db/host.random -> $(ReadOnly) -mCM ; + #/var/db/locate.database -> $(ReadOnly) -misCM ; + #/var/cron -> $(Growing) -i ; + #/var/log -> $(Growing) -i ; + #/var/run -> $(Dynamic) -i ; + #/var/mail -> $(Growing) ; + #/var/msgs/bounds -> $(ReadOnly) -smbCM ; + #/var/spool/clientmqueue -> $(Temporary) ; + #/var/spool/mqueue -> $(Temporary) ; + #!/var/tmp/vi.recover ; # perl script periodically removes this +} diff --git a/policy/twpol-Darwin.txt b/policy/twpol-Darwin.txt new file mode 100644 index 0000000..9443209 --- /dev/null +++ b/policy/twpol-Darwin.txt @@ -0,0 +1,381 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Policy file for Mac OS X # # +# September 3, 2003 # # +# ## +############################################################################## + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL + +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +#USER1=frodo ; + + + ############################################################################## + # Predefined Variables # +############################################################################## +# +# Property Masks +# +# - ignore the following properties +# + check the following properties +# +# a access timestamp (mutually exclusive with +CMSH) +# b number of blocks allocated +# c inode creation/modification timestamp +# d ID of device on which inode resides +# g group id of owner +# i inode number +# l growing files (logfiles for example) +# m modification timestamp +# n number of links +# p permission and file mode bits +# r ID of device pointed to by inode (valid only for device objects) +# s file size +# t file type +# u user id of owner +# +# C CRC-32 hash +# H HAVAL hash +# M MD5 hash +# S SHA hash +# +############################################################################## + +SEC_DEVICE = +pugsr-dintlbamcCMSH ; +SEC_DYNAMIC = +pinugt-dsrlbamcCMSH ; +SEC_READONLY = +pinugtsbmCM-drlacSH ; +SEC_GROWING = +pinugtl-dsrbamcCMSH ; + +IgnoreAll = -pinugtsdrlbamcCMSH ; +IgnoreNone = +pinugtsdrbamcCMSH-l ; +Temporary = +pugt ; + +@@section FS + + ######################################## + # ## +######################################## # +# # # +# Tripwire Binaries and Data Files # # +# ## +######################################## + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", severity=100 +) +{ + $(TWBIN)/siggen -> $(SEC_READONLY) ; + $(TWBIN)/tripwire -> $(SEC_READONLY) ; + $(TWBIN)/twadmin -> $(SEC_READONLY) ; + $(TWBIN)/twprint -> $(SEC_READONLY) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", severity=100 +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(SEC_DYNAMIC) -i ; + $(TWPOL)/tw.pol -> $(SEC_READONLY) -i ; + $(TWPOL)/tw.cfg -> $(SEC_READONLY) -i ; + $(TWLKEY)/local.key -> $(SEC_READONLY) ; + $(TWSKEY)/site.key -> $(SEC_READONLY) ; + + # don't scan the individual reports + $(TWREPORT) -> $(SEC_DYNAMIC)(recurse=0) ; + + +} + + ################################################ + # ## +################################################ # +# # # +# OS Boot and Configuration Files # # +# ## +################################################ +( + rulename = "OS Boot and Configuration Files", severity=100 +) +{ + /mach.sym -> $(SEC_READONLY)-im ; + /mach_kernel -> $(SEC_READONLY) ; + /private/etc -> $(SEC_READONLY)-m ; + + #/private/etc/appletalk.cfg -> $(SEC_READONLY)-im ; + #/private/etc/appletalk.nvram.en0 -> $(SEC_DYNAMIC) ; + /private/etc/cups/certs -> $(SEC_DYNAMIC) -i(recurse=0) ; + /private/etc/smb.conf -> $(SEC_READONLY)-im ; + + /Library -> $(SEC_READONLY) ; + /System -> $(SEC_READONLY) ; + + /Library/Printers -> $(SEC_READONLY)(recurse=2) ; + /Library/Documentation -> $(SEC_READONLY)(recurse=2) ; + /Library/Filesystems -> $(SEC_DYNAMIC)-i ; + /Library/"Application Support" -> $(SEC_DYNAMIC)-im(recurse=2) ; + + /System/Library/Filesystems -> $(SEC_DYNAMIC)-i ; + /System/Library/CoreServices -> $(SEC_READONLY)-im ; + /System/Library/Filesystems/hfs.fs -> $(SEC_DYNAMIC)(recurse=0) ; + +} + + ################################################### + # ## +################################################### # +# # # +# Mount Points # # +# ## +################################################### +( + rulename = "Mount Points", severity=60 +) +{ + / -> $(SEC_READONLY)(recurse=0) ; + /Volumes -> $(SEC_READONLY)-M (recurse=0) ; + /usr -> $(SEC_READONLY)(recurse=0) ; + +} + + + ################################################ + # ## +################################################ # +# # # +# System Devices # # +# ## +################################################ +( + rulename = "System Devices", severity=60 +) +{ + /dev -> $(SEC_DEVICE)(recurse=0) ; + #/private/var/cron/tabs/.sock -> $(SEC_DEVICE) ; + +} + + ################################################ + # ## +################################################ # +# # # +# OS Binaries and Libraries # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", severity=100 +) +{ + /bin -> $(SEC_READONLY) ; + /sbin -> $(SEC_READONLY) ; + /usr/bin -> $(SEC_READONLY) ; + /usr/lib -> $(SEC_READONLY) ; + /usr/libexec -> $(SEC_READONLY) ; + /usr/sbin -> $(SEC_READONLY) ; + #/usr/X11R6 -> $(SEC_READONLY)(recurse=2) ; # May not be present + #/usr/X11R6/man -> $(SEC_DYNAMIC)-i(recurse=1) ; # May not be present + /usr/share -> $(SEC_READONLY) ; + /usr/share/man -> $(SEC_DYNAMIC)-i(recurse=1) ; + +} + + + ################################################ + # ## +################################################ # +# # # +# OS X Applications # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", severity=100 +) +{ + /Applications -> $(SEC_READONLY)-im(recurse=2) ; + "/Applications (Mac OS 9)" -> $(SEC_READONLY) ; + + + !/Applications/Internet/P2P/Downloads ; + !/Applications/Games/"Warcraft III Folder"/Save ; + +} + + ################################################ + # ## +################################################ # +# # # +# Usr Local Files # # +# ## +################################################ +( + rulename = "Usr Local Files", severity=60 +) +{ + /usr/local -> $(SEC_READONLY) ; + #/usr/local/bin -> $(SEC_READONLY) ; + /usr/local/etc -> $(SEC_READONLY) ; + #/usr/local/sbin -> $(SEC_READONLY) ; + #/usr/local/share -> $(SEC_READONLY) ; +} + + + ################################################ + # ## +################################################ # +# # # +# Temporary Files and Directories # # +# ## +################################################ +( + rulename = "Variable System Files", severity=60 +) +{ + /private/tmp -> $(SEC_DYNAMIC)-in(recurse=0) ; + + /private/var -> $(SEC_READONLY)-i ; + /private/var/backups -> $(SEC_READONLY)-imc(severity=100) ; + #/private/var/backups/local.nidump -> $(SEC_DYNAMIC) -i(severity=100) ; + #/private/var/cron -> $(SEC_DYNAMIC) -i ; + /private/var/db -> $(SEC_READONLY)-im ; + /private/var/db/BootCache.playlist -> $(SEC_DYNAMIC) -i ; + /private/var/db/netinfo/local.nidb/Store.384 -> $(SEC_READONLY)-imc(severity=100) ; + #/private/var/db/netinfo/local.nidb/Store.672 -> $(SEC_READONLY)-imc(severity=100) ; + /private/var/db/prebindOnDemandBadFiles -> $(SEC_DYNAMIC) -i ; + /private/var/log -> $(SEC_DYNAMIC) -i ; + #/private/var/mail -> $(SEC_DYNAMIC) ; + /private/var/msgs/bounds -> $(SEC_READONLY)-smbCM ; + /private/var/root/Library/Caches -> $(SEC_DYNAMIC) -i ; + /private/var/run -> $(SEC_DYNAMIC) -i(rulename="Running Services") ; + #/private/var/slp.regfile -> $(SEC_READONLY)-im ; + /private/var/spool/clientmqueue -> $(SEC_DYNAMIC)(recurse=0) ; + /private/var/spool/mqueue -> $(SEC_DYNAMIC)(recurse=0) ; + /private/var/spool/lock -> $(SEC_DYNAMIC) -i(recurse=1) ; + /private/var/spool/cups -> $(SEC_DYNAMIC) -i(recurse=0) ; + /private/var/tmp -> $(SEC_DYNAMIC) -i(recurse=0) ; + /private/var/vm -> $(SEC_DYNAMIC)(recurse=0) ; + + /Library/Caches -> $(SEC_DYNAMIC) -i ; + /Library/Logs -> $(SEC_DYNAMIC) -i(recurse=1) ; + /Library/Preferences -> $(SEC_DYNAMIC) -i(recurse=1) ; + "/Library/Internet Plug-Ins" -> $(SEC_DYNAMIC) -i ; + + !/private/var/db/dhcpclient ; + !/private/var/db/dhcpd_leases ; + !/private/var/db/locate.database ; + !/private/var/db/SystemEntropyCache ; + !/private/var/db/samba/secrets.tdb ; + +} + + + + ################################################ + # ## +################################################ # +# # # +# Classic Environment # # +# ## +################################################ +( + rulename = "Classic Environment", severity=100 +) +{ + + /"System Folder" -> $(SEC_READONLY) ; + /"System Folder"/Preferences -> $(SEC_DYNAMIC)-i(recurse=0) ; + /"System Folder"/Extensions -> $(SEC_READONLY)-im ; + /"System Folder/Apple Menu Items" -> $(SEC_READONLY)-im(recurse=0) ; + /"System Folder"/Clipboard -> $(SEC_DYNAMIC) ; + + !/"System Folder"/VolumeNameIconPict ; + +} + + + + + ################################################### + # ## +################################################### # +# # # +# User Home Directories # # +# ## +################################################### +( + rulename = "Home Directories", severity=60 +) +{ + /Users -> $(SEC_READONLY)(recurse=0) ; # Modify as needed + + +##### +# +# USER1 as defined at top of policy +# +##### + +# /Users/$(USER1) -> $(SEC_READONLY)-mc ; +# /Users/$(USER1)/Library/Preferences -> $(SEC_DYNAMIC)-i ; +# "/Users/$(USER1)/Library/Recent Servers" -> $(SEC_DYNAMIC)-i ; +# "/Users/$(USER1)/Library/Safari" -> $(SEC_DYNAMIC)-i(recurse=3) ; +# "/Users/$(USER1)/Library/Spelling" -> $(SEC_DYNAMIC)-i ; +# "/Users/$(USER1)/Library/Mail" -> $(SEC_DYNAMIC)-i(recurse=2) ; +# "/Users/$(USER1)/Pictures/iPhoto Library" -> $(SEC_DYNAMIC)-i(recurse=1) ; +# "/Users/$(USER1)/Library/Application Support" -> $(SEC_DYNAMIC)-im(recurse=2) ; +# /Users/$(USER1)/Documents -> $(SEC_DYNAMIC)(recurse=0) ; +# /Users/$(USER1)/Desktop -> $(SEC_DYNAMIC)(recurse=0) ; + + +#!"/Users/$(USER1)/Documents/Virtual PC List" ; # These items are *huge*, and are of little value to scan. +#!"/Users/$(USER1)/Library/Preferences/Microsoft/Clipboard" ; +#!"/Users/$(USER1)/Library/Safari/Icons" ; +#!"/Users/$(USER1)/Music/iTunes" ; +#!"/Users/$(USER1)/Library/Caches" ; +#!"/Users/$(USER1)/Library/Cookies" ; +#!"/Users/$(USER1)/Library/Logs" ; +#!"/Users/$(USER1)/Library/Folding@home" ; +#!"/Users/$(USER1)/setiathome" ; +#!"/Users/$(USER1)/Documents/seti-A" ; +#!"/Users/$(USER1)/Documents/seti-B" ; +#!"/Users/$(USER1)/.tcsh_history" ; +#!"/Users/$(USER1)/.DS_Store" ; +#!"/Users/$(USER1)/Public/.DS_Store" ; +#!"/Users/$(USER1)/.jpi_cache" ; +#!"/Users/$(USER1)/.lpoptions" ; +#!"/Users/$(USER1)/.Trash" ; +} + +# +# JTI +# diff --git a/policy/twpol-FreeBSD.txt b/policy/twpol-FreeBSD.txt new file mode 100644 index 0000000..351a320 --- /dev/null +++ b/policy/twpol-FreeBSD.txt @@ -0,0 +1,655 @@ +# +# Policy file for FreeBSD +# +# $FreeBSD: ports/security/tripwire/files/twpol.txt,v 1.2 2002/03/04 16:55:21 cy Exp $ +# $Id: twpol-FreeBSD.txt,v 1.1 2003/06/08 02:00:06 pherman Exp $ + +# +# This is the example Tripwire Policy file. It is intended as a place to +# start creating your own custom Tripwire Policy file. Referring to it as +# well as the Tripwire Policy Guide should give you enough information to +# make a good custom Tripwire Policy file that better covers your +# configuration and security needs. A text version of this policy file is +# called twpol.txt. +# +# Note that this file is tuned to an install of FreeBSD using +# buildworld. If run unmodified, this file should create no errors on +# database creation, or violations on a subsiquent integrity check. +# However it is impossible for there to be one policy file for all machines, +# so this existing one errs on the side of security. Your FreeBSD +# configuration will most likey differ from the one our policy file was +# tuned to, and will therefore require some editing of the default +# Tripwire Policy file. +# +# The example policy file is best run with 'Loose Directory Checking' +# enabled. Set LOOSEDIRECTORYCHECKING=TRUE in the Tripwire Configuration +# file. +# +# Email support is not included and must be added to this file. +# Add the 'emailto=' to the rule directive section of each rule (add a comma +# after the 'severity=' line and add an 'emailto=' and include the email +# addresses you want the violation reports to go to). Addresses are +# semi-colon delimited. +# + + + +# +# Global Variable Definitions +# +# These are defined at install time by the installation script. You may +# Manually edit these if you are using this file directly and not from the +# installation script itself. +# + +@@section GLOBAL +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + +@@section FS +SEC_CRIT = $(IgnoreNone)-SHa ; # Critical files that cannot change +SEC_SUID = $(IgnoreNone)-SHa ; # Binaries with the SUID or SGID flags set +SEC_BIN = $(ReadOnly) ; # Binaries that should not change +SEC_CONFIG = $(Dynamic) ; # Config files that are changed infrequently but accessed often +SEC_TTY = $(Dynamic)-ugp ; # Tty files that change ownership at login +SEC_LOG = $(Growing) ; # Files that grow, but that should never change ownership +SEC_INVARIANT = +tpug ; # Directories that should never change permission or ownership +SIG_LOW = 33 ; # Non-critical files that are of minimal security impact +SIG_MED = 66 ; # Non-critical files that are of significant security impact +SIG_HI = 100 ; # Critical files that are significant points of vulnerability + + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", + severity = $(SIG_HI) +) +{ + $(TWBIN)/siggen -> $(SEC_BIN) ; + $(TWBIN)/tripwire -> $(SEC_BIN) ; + $(TWBIN)/twadmin -> $(SEC_BIN) ; + $(TWBIN)/twprint -> $(SEC_BIN) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", + severity = $(SIG_HI) +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(SEC_CONFIG) -i ; + $(TWPOL)/tw.pol -> $(SEC_BIN) -i ; + $(TWPOL)/tw.cfg -> $(SEC_BIN) -i ; + $(TWPOL)/twcfg.txt -> $(SEC_BIN) ; + $(TWPOL)/twpol.txt -> $(SEC_BIN) ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(SEC_BIN) ; + $(TWSKEY)/site.key -> $(SEC_BIN) ; + + #don't scan the individual reports + $(TWREPORT) -> $(SEC_CONFIG) (recurse=0) ; +} + + +# Tripwire HQ Connector Binaries +#( +# rulename = "Tripwire HQ Connector Binaries", +# severity = $(SIG_HI) +#) +#{ +# $(TWBIN)/hqagent -> $(SEC_BIN) ; +#} +# +# Tripwire HQ Connector - Configuration Files, Keys, and Logs + +# +# Note: File locations here are different than in a stock HQ Connector +# installation. This is because Tripwire 2.3 uses a different path +# structure than Tripwire 2.2.1. +# +# You may need to update your HQ Agent configuation file (or this policy +# file) to correct the paths. We have attempted to support the FHS standard +# here by placing the HQ Agent files similarly to the way Tripwire 2.3 +# places them. +# + +#( +# rulename = "Tripwire HQ Connector Data Files", +# severity = $(SIG_HI) +#) +#{ +# +# # NOTE: Removing the inode attribute because when Tripwire creates a backup +# # it does so by renaming the old file and creating a new one (which will +# # have a new inode number). Leaving inode turned on for keys, which +# # shouldn't ever change. +# +# +# $(TWBIN)/agent.cfg -> $(SEC_BIN) -i ; +# $(TWLKEY)/authentication.key -> $(SEC_BIN) ; +# $(TWDB)/tasks.dat -> $(SEC_CONFIG) ; +# $(TWDB)/schedule.dat -> $(SEC_CONFIG) ; +# +# # Uncomment if you have agent logging enabled. +# #/var/log/tripwire/agent.log -> $(SEC_LOG) ; +#} + + + +# Commonly accessed directories that should remain static with regards to owner and group +( + rulename = "Invariant Directories", + severity = $(SIG_MED) +) +{ + / -> $(SEC_INVARIANT) (recurse = false) ; + /home -> $(SEC_INVARIANT) (recurse = false) ; +} + +# +# First, root's "home" +# + +( + rulename = "Root's home", + severity = $(SIG_HI) +) +{ + # /.rhosts -> $(SEC_CRIT) ; + /.profile -> $(SEC_CRIT) ; + /.cshrc -> $(SEC_CRIT) ; + /.login -> $(SEC_CRIT) ; + # /.exrc -> $(SEC_CRIT) ; + # /.logout -> $(SEC_CRIT) ; + # /.forward -> $(SEC_CRIT) ; + /root -> $(SEC_CRIT) (recurse = true) ; + !/root/.history ; + !/root/.bash_history ; + # !/root/.lsof_SYSTEM_NAME ; # Uncomment if lsof is installed +} + + +# +# FreeBSD Kernel +# + +( + rulename = "FreeBSD Kernel", + severity = $(SIG_HI) +) +{ + /kernel -> $(SEC_CRIT) ; + /kernel.old -> $(SEC_CRIT) ; + /kernel.GENERIC -> $(SEC_CRIT) ; +} + + +# +# FreeBSD Modules +# + +( + rulename = "FreeBSD Modules", + severity = $(SIG_HI) +) +{ + /modules -> $(SEC_CRIT) (recurse = true) ; + /modules.old -> $(SEC_CRIT) (recurse = true) ; + # /lkm -> $(SEC_CRIT) (recurse = true) ; # uncomment if using lkm kld +} + + +# +# System Administration Programs +# + +( + rulename = "System Administration Programs", + severity = $(SIG_HI) +) +{ + /sbin -> $(SEC_CRIT) (recurse = true) ; + /usr/sbin -> $(SEC_CRIT) (recurse = true) ; +} + + +# +# User Utilities +# + +( + rulename = "User Utilities", + severity = $(SIG_HI) +) +{ + /bin -> $(SEC_CRIT) (recurse = true) ; + /usr/bin -> $(SEC_CRIT) (recurse = true) ; +} + + +# +# /dev +# + +( + rulename = "/dev", + severity = $(SIG_HI) +) +{ + /dev -> $(Device) (recurse = true) ; + !/dev/vga ; + !/dev/dri ; + /dev/console -> $(SEC_TTY) ; + /dev/ttyv0 -> $(SEC_TTY) ; + /dev/ttyv1 -> $(SEC_TTY) ; + /dev/ttyv2 -> $(SEC_TTY) ; + /dev/ttyv3 -> $(SEC_TTY) ; + /dev/ttyv4 -> $(SEC_TTY) ; + /dev/ttyv5 -> $(SEC_TTY) ; + /dev/ttyv6 -> $(SEC_TTY) ; + /dev/ttyv7 -> $(SEC_TTY) ; + /dev/ttyp0 -> $(SEC_TTY) ; + /dev/ttyp1 -> $(SEC_TTY) ; + /dev/ttyp2 -> $(SEC_TTY) ; + /dev/ttyp3 -> $(SEC_TTY) ; + /dev/ttyp4 -> $(SEC_TTY) ; + /dev/ttyp5 -> $(SEC_TTY) ; + /dev/ttyp6 -> $(SEC_TTY) ; + /dev/ttyp7 -> $(SEC_TTY) ; + /dev/ttyp8 -> $(SEC_TTY) ; + /dev/ttyp9 -> $(SEC_TTY) ; + /dev/ttypa -> $(SEC_TTY) ; + /dev/ttypb -> $(SEC_TTY) ; + /dev/ttypc -> $(SEC_TTY) ; + /dev/ttypd -> $(SEC_TTY) ; + /dev/ttype -> $(SEC_TTY) ; + /dev/ttypf -> $(SEC_TTY) ; + /dev/ttypg -> $(SEC_TTY) ; + /dev/ttyph -> $(SEC_TTY) ; + /dev/ttypi -> $(SEC_TTY) ; + /dev/ttypj -> $(SEC_TTY) ; + /dev/ttypl -> $(SEC_TTY) ; + /dev/ttypm -> $(SEC_TTY) ; + /dev/ttypn -> $(SEC_TTY) ; + /dev/ttypo -> $(SEC_TTY) ; + /dev/ttypp -> $(SEC_TTY) ; + /dev/ttypq -> $(SEC_TTY) ; + /dev/ttypr -> $(SEC_TTY) ; + /dev/ttyps -> $(SEC_TTY) ; + /dev/ttypt -> $(SEC_TTY) ; + /dev/ttypu -> $(SEC_TTY) ; + /dev/ttypv -> $(SEC_TTY) ; + /dev/cuaa0 -> $(SEC_TTY) ; # modem +} + + +# +# /etc +# + +( + rulename = "/etc", + severity = $(SIG_HI) +) +{ + /etc -> $(SEC_CRIT) (recurse = true) ; + # /etc/mail/aliases -> $(SEC_CONFIG) ; + /etc/dumpdates -> $(SEC_CONFIG) ; + /etc/motd -> $(SEC_CONFIG) ; + !/etc/ppp/connect-errors ; + /etc/skeykeys -> $(SEC_CONFIG) ; + # Uncomment the following 4 lines if your password file does not change + # /etc/passwd -> $(SEC_CONFIG) ; + # /etc/master.passwd -> $(SEC_CONFIG) ; + # /etc/pwd.db -> $(SEC_CONFIG) ; + # /etc/spwd.db -> $(SEC_CONFIG) ; +} + + +# +# Copatibility (Linux) +# + +( + rulename = "Linux Compatibility", + severity = $(SIG_HI) +) +{ + /compat -> $(SEC_CRIT) (recurse = true) ; +# +# Uncomment the following if Linux compatibility is used. Replace +# HOSTNAME1 and HOSTNAME2 with the hosts that have Linux emulation port +# installed. +# +#@@ifhost HOSTNAME1 || HOSTNAME2 +# /compat/linux/etc -> $(SEC_INVARIANT) (recurse = false) ; +# /compat/linux/etc/X11 -> $(SEC_CONFIG) (recurse = true) ; +# /compat/linux/etc/pam.d -> $(SEC_CONFIG) (recurse = true) ; +# /compat/linux/etc/profile.d -> $(SEC_CONFIG) (recurse = true) ; +# /compat/linux/etc/real -> $(SEC_CONFIG) (recurse = true) ; +# /compat/linux/etc/bashrc -> $(SEC_CONFIG) ; +# /compat/linux/etc/csh.login -> $(SEC_CONFIG) ; +# /compat/linux/etc/host.conf -> $(SEC_CONFIG) ; +# /compat/linux/etc/hosts.allow -> $(SEC_CONFIG) ; +# /compat/linux/etc/hosts.deny -> $(SEC_CONFIG) ; +# /compat/linux/etc/info-dir -> $(SEC_CONFIG) ; +# /compat/linux/etc/inputrc -> $(SEC_CONFIG) ; +# /compat/linux/etc/ld.so.conf -> $(SEC_CONFIG) ; +# /compat/linux/etc/nsswitch.conf -> $(SEC_CONFIG) ; +# /compat/linux/etc/profile -> $(SEC_CONFIG) ; +# /compat/linux/etc/redhat-release -> $(SEC_CONFIG) ; +# /compat/linux/etc/rpc -> $(SEC_CONFIG) ; +# /compat/linux/etc/securetty -> $(SEC_CONFIG) ; +# /compat/linux/etc/shells -> $(SEC_CONFIG) ; +# /compat/linux/etc/termcap -> $(SEC_CONFIG) ; +# /compat/linux/etc/yp.conf -> $(SEC_CONFIG) ; +# !/compat/linux/etc/ld.so.cache ; +# !/compat/linux/var/spool/mail ; +#@@endif +} + + +# +# Libraries, include files, and other system files +# + +( + rulename = "Libraries, include files, and other system files", + severity = $(SIG_HI) +) +{ + /usr/include -> $(SEC_CRIT) (recurse = true) ; + /usr/lib -> $(SEC_CRIT) (recurse = true) ; + /usr/libdata -> $(SEC_CRIT) (recurse = true) ; + /usr/libexec -> $(SEC_CRIT) (recurse = true) ; + /usr/share -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man -> $(SEC_CONFIG) ; + !/usr/share/man/whatis ; + !/usr/share/man/.glimpse_filenames ; + !/usr/share/man/.glimpse_filenames_index ; + !/usr/share/man/.glimpse_filetimes ; + !/usr/share/man/.glimpse_filters ; + !/usr/share/man/.glimpse_index ; + !/usr/share/man/.glimpse_messages ; + !/usr/share/man/.glimpse_partitions ; + !/usr/share/man/.glimpse_statistics ; + !/usr/share/man/.glimpse_turbo ; + /usr/share/man/man1 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man2 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man3 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man4 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man5 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man6 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man7 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man8 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/man9 -> $(SEC_CRIT) (recurse = true) ; + /usr/share/man/mann -> $(SEC_CRIT) (recurse = true) ; + ! /usr/share/man/cat1 ; + ! /usr/share/man/cat2 ; + ! /usr/share/man/cat3 ; + ! /usr/share/man/cat4 ; + ! /usr/share/man/cat5 ; + ! /usr/share/man/cat6 ; + ! /usr/share/man/cat7 ; + ! /usr/share/man/cat8 ; + ! /usr/share/man/cat9 ; + ! /usr/share/man/catl ; + ! /usr/share/man/catn ; + /usr/share/perl/man -> $(SEC_CONFIG) ; + !/usr/share/perl/man/whatis ; + !/usr/share/perl/man/.glimpse_filenames ; + !/usr/share/perl/man/.glimpse_filenames_index ; + !/usr/share/perl/man/.glimpse_filetimes ; + !/usr/share/perl/man/.glimpse_filters ; + !/usr/share/perl/man/.glimpse_index ; + !/usr/share/perl/man/.glimpse_messages ; + !/usr/share/perl/man/.glimpse_partitions ; + !/usr/share/perl/man/.glimpse_statistics ; + !/usr/share/perl/man/.glimpse_turbo ; + /usr/share/perl/man/man3 -> $(SEC_CRIT) (recurse = true) ; + ! /usr/share/perl/man/cat3 ; + /usr/local/lib/perl5/5.00503/man -> $(SEC_CONFIG) ; + ! /usr/local/lib/perl5/5.00503/man/whatis ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_filters ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_filetimes ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_messages ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_statistics ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_index ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_turbo ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_partitions ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_filenames ; + ! /usr/local/lib/perl5/5.00503/man/.glimpse_filenames_index ; + /usr/local/lib/perl5/5.00503/man/man3 -> $(SEC_CRIT) (recurse = true) ; + ! /usr/local/lib/perl5/5.00503/man/cat3 ; +} + + +# +# X11R6 +# + +( + rulename = "X11R6", + severity = $(SIG_HI) +) +{ + /usr/X11R6 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/lib/X11/xdm -> $(SEC_CONFIG) (recurse = true) ; + !/usr/X11R6/lib/X11/xdm/xdm-errors ; + !/usr/X11R6/lib/X11/xdm/authdir/authfiles ; + !/usr/X11R6/lib/X11/xdm/xdm-pid ; + /usr/X11R6/lib/X11/xkb/compiled -> $(SEC_CONFIG) (recurse = true) ; + /usr/X11R6/man -> $(SEC_CONFIG) ; + !/usr/X11R6/man/whatis ; + !/usr/X11R6/man/.glimpse_filenames ; + !/usr/X11R6/man/.glimpse_filenames_index ; + !/usr/X11R6/man/.glimpse_filetimes ; + !/usr/X11R6/man/.glimpse_filters ; + !/usr/X11R6/man/.glimpse_index ; + !/usr/X11R6/man/.glimpse_messages ; + !/usr/X11R6/man/.glimpse_partitions ; + !/usr/X11R6/man/.glimpse_statistics ; + !/usr/X11R6/man/.glimpse_turbo ; + /usr/X11R6/man/man1 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man2 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man3 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man4 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man5 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man6 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man7 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man8 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/man9 -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/manl -> $(SEC_CRIT) (recurse = true) ; + /usr/X11R6/man/mann -> $(SEC_CRIT) (recurse = true) ; + ! /usr/X11R6/man/cat1 ; + ! /usr/X11R6/man/cat2 ; + ! /usr/X11R6/man/cat3 ; + ! /usr/X11R6/man/cat4 ; + ! /usr/X11R6/man/cat5 ; + ! /usr/X11R6/man/cat6 ; + ! /usr/X11R6/man/cat7 ; + ! /usr/X11R6/man/cat8 ; + ! /usr/X11R6/man/cat9 ; + ! /usr/X11R6/man/catl ; + ! /usr/X11R6/man/catn ; +} + + +# +# sources +# + +( + rulename = "Sources", + severity = $(SIG_HI) +) +{ + /usr/src -> $(SEC_CRIT) (recurse = true) ; + /usr/src/sys/compile -> $(SEC_CONFIG) (recurse = false) ; +} + + +# +# NIS +# + +( + rulename = "NIS", + severity = $(SIG_HI) +) +{ + /var/yp -> $(SEC_CRIT) (recurse = true) ; + !/var/yp/binding ; +} + + +# +# Temporary directories +# +( + rulename = "Temporary directories", + recurse = false, + severity = $(SIG_LOW) +) +{ + /usr/tmp -> $(SEC_INVARIANT) ; + /var/tmp -> $(SEC_INVARIANT) ; + /var/preserve -> $(SEC_INVARIANT) ; + /tmp -> $(SEC_INVARIANT) ; +} + +# +# Local files +# + +( + rulename = "Local files", + severity = $(SIG_MED) +) +{ + /usr/local/bin -> $(SEC_BIN) (recurse = true) ; + /usr/local/sbin -> $(SEC_BIN) (recurse = true) ; + /usr/local/etc -> $(SEC_BIN) (recurse = true) ; + /usr/local/lib -> $(SEC_BIN) (recurse = true ) ; + /usr/local/libexec -> $(SEC_BIN) (recurse = true ) ; + /usr/local/share -> $(SEC_BIN) (recurse = true ) ; + /usr/local/man -> $(SEC_CONFIG) ; + !/usr/local/man/whatis ; + !/usr/local/man/.glimpse_filenames ; + !/usr/local/man/.glimpse_filenames_index ; + !/usr/local/man/.glimpse_filetimes ; + !/usr/local/man/.glimpse_filters ; + !/usr/local/man/.glimpse_index ; + !/usr/local/man/.glimpse_messages ; + !/usr/local/man/.glimpse_partitions ; + !/usr/local/man/.glimpse_statistics ; + !/usr/local/man/.glimpse_turbo ; + /usr/local/man/man1 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man2 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man3 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man4 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man5 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man6 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man7 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man8 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/man9 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/manl -> $(SEC_CRIT) (recurse = true) ; + /usr/local/man/mann -> $(SEC_CRIT) (recurse = true) ; + ! /usr/local/man/cat1 ; + ! /usr/local/man/cat2 ; + ! /usr/local/man/cat3 ; + ! /usr/local/man/cat4 ; + ! /usr/local/man/cat5 ; + ! /usr/local/man/cat6 ; + ! /usr/local/man/cat7 ; + ! /usr/local/man/cat8 ; + ! /usr/local/man/cat9 ; + ! /usr/local/man/catl ; + ! /usr/local/man/catn ; + /usr/local/krb5 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man -> $(SEC_CONFIG) ; + !/usr/local/krb5/man/whatis ; + !/usr/local/krb5/man/.glimpse_filenames ; + !/usr/local/krb5/man/.glimpse_filenames_index ; + !/usr/local/krb5/man/.glimpse_filetimes ; + !/usr/local/krb5/man/.glimpse_filters ; + !/usr/local/krb5/man/.glimpse_index ; + !/usr/local/krb5/man/.glimpse_messages ; + !/usr/local/krb5/man/.glimpse_partitions ; + !/usr/local/krb5/man/.glimpse_statistics ; + !/usr/local/krb5/man/.glimpse_turbo ; + /usr/local/krb5/man/man1 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man2 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man3 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man4 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man5 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man6 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man7 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man8 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/man9 -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/manl -> $(SEC_CRIT) (recurse = true) ; + /usr/local/krb5/man/mann -> $(SEC_CRIT) (recurse = true) ; + ! /usr/local/krb5/man/cat1 ; + ! /usr/local/krb5/man/cat2 ; + ! /usr/local/krb5/man/cat3 ; + ! /usr/local/krb5/man/cat4 ; + ! /usr/local/krb5/man/cat5 ; + ! /usr/local/krb5/man/cat6 ; + ! /usr/local/krb5/man/cat7 ; + ! /usr/local/krb5/man/cat8 ; + ! /usr/local/krb5/man/cat9 ; + ! /usr/local/krb5/man/catl ; + ! /usr/local/krb5/man/catn ; + /usr/local/www -> $(SEC_CONFIG) (recurse = true) ; +} + + +( + rulename = "Security Control", + severity = $(SIG_HI) +) +{ + /etc/group -> $(SEC_CRIT) ; + /etc/crontab -> $(SEC_CRIT) ; +} + +#============================================================================= +# +# Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, +# Inc. in the United States and other countries. All rights reserved. +# +# FreeBSD is a registered trademark of the FreeBSD Project Inc. +# +# UNIX is a registered trademark of The Open Group. +# +#============================================================================= +# +# Permission is granted to make and distribute verbatim copies of this document +# provided the copyright notice and this permission notice are preserved on all +# copies. +# +# Permission is granted to copy and distribute modified versions of this +# document under the conditions for verbatim copying, provided that the entire +# resulting derived work is distributed under the terms of a permission notice +# identical to this one. +# +# Permission is granted to copy and distribute translations of this document +# into another language, under the above conditions for modified versions, +# except that this permission notice may be stated in a translation approved by +# Tripwire, Inc. +# +# DCM diff --git a/policy/twpol-GENERIC.txt b/policy/twpol-GENERIC.txt new file mode 100644 index 0000000..e30ae4c --- /dev/null +++ b/policy/twpol-GENERIC.txt @@ -0,0 +1,1107 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Generic Policy file # # +# V1.2.0rh # # +# August 9, 2001 # # +# ## +############################################################################## + + + ############################################################################## + # ## +############################################################################## # +# # # +# This is the example Tripwire Policy file. It is intended as a place to # # +# start creating your own custom Tripwire Policy file. Referring to it as # # +# well as the Tripwire Policy Guide should give you enough information to # # +# make a good custom Tripwire Policy file that better covers your # # +# configuration and security needs. A text version of this policy file is # # +# called twpol.txt. # # +# # # +# Note that this file is tuned to an 'everything' install of Red Hat Linux. # # +# If run unmodified, this file should create no errors on database # # +# creation, or violations on a subsiquent integrity check. However, it is # # +# impossible for there to be one policy file for all machines, so this # # +# existing one errs on the side of security. Your Linux configuration will # # +# most likey differ from the one our policy file was tuned to, and will # # +# therefore require some editing of the default Tripwire Policy file. # # +# # # +# The example policy file is best run with 'Loose Directory Checking' # # +# enabled. Set LOOSEDIRECTORYCHECKING=TRUE in the Tripwire Configuration # # +# file. # # +# # # +# Email support is not included and must be added to this file. # # +# Add the 'emailto=' to the rule directive section of each rule (add a comma # # +# after the 'severity=' line and add an 'emailto=' and include the email # # +# addresses you want the violation reports to go to). Addresses are # # +# semi-colon delimited. # # +# ## +############################################################################## + + + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# Manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + +@@section FS +SEC_CRIT = $(IgnoreNone)-SHa ; # Critical files that cannot change +SEC_SUID = $(IgnoreNone)-SHa ; # Binaries with the SUID or SGID flags set +SEC_BIN = $(ReadOnly) ; # Binaries that should not change +SEC_CONFIG = $(Dynamic) ; # Config files that are changed infrequently but accessed often +SEC_LOG = $(Growing) ; # Files that grow, but that should never change ownership +SEC_INVARIANT = +tpug ; # Directories that should never change permission or ownership +SIG_LOW = 33 ; # Non-critical files that are of minimal security impact +SIG_MED = 66 ; # Non-critical files that are of significant security impact +SIG_HI = 100 ; # Critical files that are significant points of vulnerability + + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", + severity = $(SIG_HI) +) +{ + $(TWBIN)/siggen -> $(SEC_BIN) ; + $(TWBIN)/tripwire -> $(SEC_BIN) ; + $(TWBIN)/twadmin -> $(SEC_BIN) ; + $(TWBIN)/twprint -> $(SEC_BIN) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", + severity = $(SIG_HI) +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(SEC_CONFIG) -i ; + $(TWPOL)/tw.pol -> $(SEC_BIN) -i ; + $(TWPOL)/tw.cfg -> $(SEC_BIN) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(SEC_BIN) ; + $(TWSKEY)/site.key -> $(SEC_BIN) ; + + #don't scan the individual reports + $(TWREPORT) -> $(SEC_CONFIG) (recurse=0) ; +} + + +# Tripwire HQ Connector Binaries +#( +# rulename = "Tripwire HQ Connector Binaries", +# severity = $(SIG_HI) +#) +#{ +# $(TWBIN)/hqagent -> $(SEC_BIN) ; +#} +# +# Tripwire HQ Connector - Configuration Files, Keys, and Logs + + ############################################################################## + # ## +############################################################################## # +# # # +# Note: File locations here are different than in a stock HQ Connector # # +# installation. This is because Tripwire 2.3 uses a different path # # +# structure than Tripwire 2.2.1. # # +# # # +# You may need to update your HQ Agent configuation file (or this policy # # +# file) to correct the paths. We have attempted to support the FHS standard # # +# here by placing the HQ Agent files similarly to the way Tripwire 2.3 # # +# places them. # # +# ## +############################################################################## + +#( +# rulename = "Tripwire HQ Connector Data Files", +# severity = $(SIG_HI) +#) +#{ +# ############################################################################# +# ############################################################################## +# # NOTE: Removing the inode attribute because when Tripwire creates a backup ## +# # it does so by renaming the old file and creating a new one (which will ## +# # have a new inode number). Leaving inode turned on for keys, which ## +# # shouldn't ever change. ## +# ############################################################################# +# +# $(TWBIN)/agent.cfg -> $(SEC_BIN) -i ; +# $(TWLKEY)/authentication.key -> $(SEC_BIN) ; +# $(TWDB)/tasks.dat -> $(SEC_CONFIG) ; +# $(TWDB)/schedule.dat -> $(SEC_CONFIG) ; +# +# # Uncomment if you have agent logging enabled. +# #/var/log/tripwire/agent.log -> $(SEC_LOG) ; +#} + + + +# Commonly accessed directories that should remain static with regards to owner and group +( + rulename = "Invariant Directories", + severity = $(SIG_MED) +) +{ + / -> $(SEC_INVARIANT) (recurse = 0) ; + /home -> $(SEC_INVARIANT) (recurse = 0) ; + /etc -> $(SEC_INVARIANT) (recurse = 0) ; +} + ################################################ + # ## +################################################ # +# # # +# File System and Disk Administration Programs # # +# ## +################################################ + +( + rulename = "File System and Disk Administraton Programs", + severity = $(SIG_HI) +) +{ + /sbin/accton -> $(SEC_CRIT) ; + /sbin/badblocks -> $(SEC_CRIT) ; + /sbin/busybox -> $(SEC_CRIT) ; + /sbin/busybox.anaconda -> $(SEC_CRIT) ; + /sbin/convertquota -> $(SEC_CRIT) ; + /sbin/dosfsck -> $(SEC_CRIT) ; + /sbin/debugfs -> $(SEC_CRIT) ; + /sbin/debugreiserfs -> $(SEC_CRIT) ; + /sbin/dumpe2fs -> $(SEC_CRIT) ; + /sbin/dump -> $(SEC_CRIT) ; + /sbin/dump.static -> $(SEC_CRIT) ; + # /sbin/e2fsadm -> $(SEC_CRIT) ; tune2fs? + /sbin/e2fsck -> $(SEC_CRIT) ; + /sbin/e2label -> $(SEC_CRIT) ; + /sbin/fdisk -> $(SEC_CRIT) ; + /sbin/fsck -> $(SEC_CRIT) ; + /sbin/fsck.ext2 -> $(SEC_CRIT) ; + /sbin/fsck.ext3 -> $(SEC_CRIT) ; + /sbin/fsck.minix -> $(SEC_CRIT) ; + /sbin/fsck.msdos -> $(SEC_CRIT) ; + /sbin/fsck.vfat -> $(SEC_CRIT) ; + /sbin/ftl_check -> $(SEC_CRIT) ; + /sbin/ftl_format -> $(SEC_CRIT) ; + /sbin/hdparm -> $(SEC_CRIT) ; + #/sbin/lvchange -> $(SEC_CRIT) ; + #/sbin/lvcreate -> $(SEC_CRIT) ; + #/sbin/lvdisplay -> $(SEC_CRIT) ; + #/sbin/lvextend -> $(SEC_CRIT) ; + #/sbin/lvmchange -> $(SEC_CRIT) ; + #/sbin/lvmcreate_initrd -> $(SEC_CRIT) ; + #/sbin/lvmdiskscan -> $(SEC_CRIT) ; + #/sbin/lvmsadc -> $(SEC_CRIT) ; + #/sbin/lvmsar -> $(SEC_CRIT) ; + #/sbin/lvreduce -> $(SEC_CRIT) ; + #/sbin/lvremove -> $(SEC_CRIT) ; + #/sbin/lvrename -> $(SEC_CRIT) ; + #/sbin/lvscan -> $(SEC_CRIT) ; + /sbin/mkbootdisk -> $(SEC_CRIT) ; + /sbin/mkdosfs -> $(SEC_CRIT) ; + /sbin/mke2fs -> $(SEC_CRIT) ; + /sbin/mkfs -> $(SEC_CRIT) ; + /sbin/mkfs.bfs -> $(SEC_CRIT) ; + /sbin/mkfs.ext2 -> $(SEC_CRIT) ; + /sbin/mkfs.minix -> $(SEC_CRIT) ; + /sbin/mkfs.msdos -> $(SEC_CRIT) ; + /sbin/mkfs.vfat -> $(SEC_CRIT) ; + /sbin/mkinitrd -> $(SEC_CRIT) ; + #/sbin/mkpv -> $(SEC_CRIT) ; + /sbin/mkraid -> $(SEC_CRIT) ; + /sbin/mkreiserfs -> $(SEC_CRIT) ; + /sbin/mkswap -> $(SEC_CRIT) ; + #/sbin/mtx -> $(SEC_CRIT) ; + /sbin/pam_console_apply -> $(SEC_CRIT) ; + /sbin/parted -> $(SEC_CRIT) ; + /sbin/pcinitrd -> $(SEC_CRIT) ; + #/sbin/pvchange -> $(SEC_CRIT) ; + #/sbin/pvcreate -> $(SEC_CRIT) ; + #/sbin/pvdata -> $(SEC_CRIT) ; + #/sbin/pvdisplay -> $(SEC_CRIT) ; + #/sbin/pvmove -> $(SEC_CRIT) ; + #/sbin/pvscan -> $(SEC_CRIT) ; + /sbin/quotacheck -> $(SEC_CRIT) ; + /sbin/quotaon -> $(SEC_CRIT) ; + /sbin/raidstart -> $(SEC_CRIT) ; + /sbin/reiserfsck -> $(SEC_CRIT) ; + /sbin/resize2fs -> $(SEC_CRIT) ; + /sbin/resize_reiserfs -> $(SEC_CRIT) ; + /sbin/restore -> $(SEC_CRIT) ; + /sbin/restore.static -> $(SEC_CRIT) ; + /sbin/scsi_info -> $(SEC_CRIT) ; + /sbin/sfdisk -> $(SEC_CRIT) ; + /sbin/stinit -> $(SEC_CRIT) ; + #/sbin/tapeinfo -> $(SEC_CRIT) ; + /sbin/tune2fs -> $(SEC_CRIT) ; + /sbin/unpack -> $(SEC_CRIT) ; + /sbin/update -> $(SEC_CRIT) ; + #/sbin/vgcfgbackup -> $(SEC_CRIT) ; + #/sbin/vgcfgrestore -> $(SEC_CRIT) ; + #/sbin/vgchange -> $(SEC_CRIT) ; + #/sbin/vgck -> $(SEC_CRIT) ; + #/sbin/vgcreate -> $(SEC_CRIT) ; + #/sbin/vgdisplay -> $(SEC_CRIT) ; + #/sbin/vgexport -> $(SEC_CRIT) ; + #/sbin/vgextend -> $(SEC_CRIT) ; + #/sbin/vgimport -> $(SEC_CRIT) ; + #/sbin/vgmerge -> $(SEC_CRIT) ; + #/sbin/vgmknodes -> $(SEC_CRIT) ; + #/sbin/vgreduce -> $(SEC_CRIT) ; + #/sbin/vgremove -> $(SEC_CRIT) ; + #/sbin/vgrename -> $(SEC_CRIT) ; + #/sbin/vgscan -> $(SEC_CRIT) ; + #/sbin/vgsplit -> $(SEC_CRIT) ; + /bin/chgrp -> $(SEC_CRIT) ; + /bin/chmod -> $(SEC_CRIT) ; + /bin/chown -> $(SEC_CRIT) ; + /bin/cp -> $(SEC_CRIT) ; + /bin/cpio -> $(SEC_CRIT) ; + /bin/mount -> $(SEC_CRIT) ; + /bin/umount -> $(SEC_CRIT) ; + /bin/mkdir -> $(SEC_CRIT) ; + /bin/mknod -> $(SEC_CRIT) ; + /bin/mktemp -> $(SEC_CRIT) ; + /bin/rm -> $(SEC_CRIT) ; + /bin/rmdir -> $(SEC_CRIT) ; + /bin/touch -> $(SEC_CRIT) ; +} + + ################################## + # ## +################################## # +# # # +# Kernel Administration Programs # # +# ## +################################## + +( + rulename = "Kernel Administration Programs", + severity = $(SIG_HI) +) +{ + /sbin/adjtimex -> $(SEC_CRIT) ; + /sbin/ctrlaltdel -> $(SEC_CRIT) ; + /sbin/depmod -> $(SEC_CRIT) ; + /sbin/insmod -> $(SEC_CRIT) ; + /sbin/insmod.static -> $(SEC_CRIT) ; + /sbin/insmod_ksymoops_clean -> $(SEC_CRIT) ; + /sbin/klogd -> $(SEC_CRIT) ; + /sbin/ldconfig -> $(SEC_CRIT) ; + /sbin/minilogd -> $(SEC_CRIT) ; + /sbin/modinfo -> $(SEC_CRIT) ; + #/sbin/nuactlun -> $(SEC_CRIT) ; + #/sbin/nuscsitcpd -> $(SEC_CRIT) ; + /sbin/pivot_root -> $(SEC_CRIT) ; + /sbin/sndconfig -> $(SEC_CRIT) ; + /sbin/sysctl -> $(SEC_CRIT) ; +} + + ####################### + # ## +####################### # +# # # +# Networking Programs # # +# ## +####################### + +( + rulename = "Networking Programs", + severity = $(SIG_HI) +) +{ + /etc/sysconfig/network-scripts/ifdown -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-cipcb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ippp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ipv6 -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-isdn -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-post -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-ppp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-sit -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifdown-sl -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-aliases -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-cipcb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ippp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ipv6 -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-isdn -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-plip -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-plusb -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-post -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-ppp -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-routes -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-sit -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-sl -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/ifup-wireless -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/network-functions -> $(SEC_CRIT) ; + /etc/sysconfig/network-scripts/network-functions-ipv6 -> $(SEC_CRIT) ; + /bin/ping -> $(SEC_CRIT) ; + /sbin/agetty -> $(SEC_CRIT) ; + /sbin/arp -> $(SEC_CRIT) ; + /sbin/arping -> $(SEC_CRIT) ; + /sbin/dhcpcd -> $(SEC_CRIT) ; + /sbin/ether-wake -> $(SEC_CRIT) ; + #/sbin/getty -> $(SEC_CRIT) ; + /sbin/ifcfg -> $(SEC_CRIT) ; + /sbin/ifconfig -> $(SEC_CRIT) ; + /sbin/ifdown -> $(SEC_CRIT) ; + /sbin/ifenslave -> $(SEC_CRIT) ; + /sbin/ifport -> $(SEC_CRIT) ; + /sbin/ifup -> $(SEC_CRIT) ; + /sbin/ifuser -> $(SEC_CRIT) ; + /sbin/ip -> $(SEC_CRIT) ; + /sbin/ip6tables -> $(SEC_CRIT) ; + /sbin/ipchains -> $(SEC_CRIT) ; + /sbin/ipchains-restore -> $(SEC_CRIT) ; + /sbin/ipchains-save -> $(SEC_CRIT) ; + /sbin/ipfwadm -> $(SEC_CRIT) ; + /sbin/ipmaddr -> $(SEC_CRIT) ; + /sbin/iptables -> $(SEC_CRIT) ; + /sbin/iptables-restore -> $(SEC_CRIT) ; + /sbin/iptables-save -> $(SEC_CRIT) ; + /sbin/iptunnel -> $(SEC_CRIT) ; + #/sbin/ipvsadm -> $(SEC_CRIT) ; + #/sbin/ipvsadm-restore -> $(SEC_CRIT) ; + #/sbin/ipvsadm-save -> $(SEC_CRIT) ; + /sbin/ipx_configure -> $(SEC_CRIT) ; + /sbin/ipx_interface -> $(SEC_CRIT) ; + /sbin/ipx_internal_net -> $(SEC_CRIT) ; + /sbin/iwconfig -> $(SEC_CRIT) ; + /sbin/iwgetid -> $(SEC_CRIT) ; + /sbin/iwlist -> $(SEC_CRIT) ; + /sbin/iwpriv -> $(SEC_CRIT) ; + /sbin/iwspy -> $(SEC_CRIT) ; + /sbin/mgetty -> $(SEC_CRIT) ; + /sbin/mingetty -> $(SEC_CRIT) ; + /sbin/nameif -> $(SEC_CRIT) ; + /sbin/netreport -> $(SEC_CRIT) ; + /sbin/plipconfig -> $(SEC_CRIT) ; + /sbin/portmap -> $(SEC_CRIT) ; + /sbin/ppp-watch -> $(SEC_CRIT) ; + #/sbin/rarp -> $(SEC_CRIT) ; + /sbin/route -> $(SEC_CRIT) ; + /sbin/slattach -> $(SEC_CRIT) ; + /sbin/tc -> $(SEC_CRIT) ; + #/sbin/uugetty -> $(SEC_CRIT) ; + /sbin/vgetty -> $(SEC_CRIT) ; + /sbin/ypbind -> $(SEC_CRIT) ; +} + + ################################## + # ## +################################## # +# # # +# System Administration Programs # # +# ## +################################## + +( + rulename = "System Administration Programs", + severity = $(SIG_HI) +) +{ + /sbin/chkconfig -> $(SEC_CRIT) ; + /sbin/fuser -> $(SEC_CRIT) ; + /sbin/halt -> $(SEC_CRIT) ; + /sbin/init -> $(SEC_CRIT) ; + /sbin/initlog -> $(SEC_CRIT) ; + /sbin/install-info -> $(SEC_CRIT) ; + /sbin/killall5 -> $(SEC_CRIT) ; + #/sbin/linuxconf -> $(SEC_CRIT) ; + #/sbin/linuxconf-auth -> $(SEC_CRIT) ; + /sbin/pam_tally -> $(SEC_CRIT) ; + /sbin/pwdb_chkpwd -> $(SEC_CRIT) ; + #/sbin/remadmin -> $(SEC_CRIT) ; + /sbin/rescuept -> $(SEC_CRIT) ; + /sbin/rmt -> $(SEC_CRIT) ; + /sbin/rpc.lockd -> $(SEC_CRIT) ; + /sbin/rpc.statd -> $(SEC_CRIT) ; + /sbin/rpcdebug -> $(SEC_CRIT) ; + /sbin/service -> $(SEC_CRIT) ; + /sbin/setsysfont -> $(SEC_CRIT) ; + /sbin/shutdown -> $(SEC_CRIT) ; + /sbin/sulogin -> $(SEC_CRIT) ; + /sbin/swapon -> $(SEC_CRIT) ; + /sbin/syslogd -> $(SEC_CRIT) ; + /sbin/unix_chkpwd -> $(SEC_CRIT) ; + /bin/pwd -> $(SEC_CRIT) ; + /bin/uname -> $(SEC_CRIT) ; +} + + ######################################## + # ## +######################################## # +# # # +# Hardware and Device Control Programs # # +# ## +######################################## +( + rulename = "Hardware and Device Control Programs", + severity = $(SIG_HI) +) +{ + /bin/setserial -> $(SEC_CRIT) ; + /bin/sfxload -> $(SEC_CRIT) ; + /sbin/blockdev -> $(SEC_CRIT) ; + /sbin/cardctl -> $(SEC_CRIT) ; + /sbin/cardmgr -> $(SEC_CRIT) ; + /sbin/cbq -> $(SEC_CRIT) ; + /sbin/dump_cis -> $(SEC_CRIT) ; + /sbin/elvtune -> $(SEC_CRIT) ; + /sbin/hotplug -> $(SEC_CRIT) ; + /sbin/hwclock -> $(SEC_CRIT) ; + /sbin/ide_info -> $(SEC_CRIT) ; + #/sbin/isapnp -> $(SEC_CRIT) ; + /sbin/kbdrate -> $(SEC_CRIT) ; + /sbin/losetup -> $(SEC_CRIT) ; + /sbin/lspci -> $(SEC_CRIT) ; + /sbin/lspnp -> $(SEC_CRIT) ; + /sbin/mii-tool -> $(SEC_CRIT) ; + /sbin/pack_cis -> $(SEC_CRIT) ; + #/sbin/pnpdump -> $(SEC_CRIT) ; + /sbin/probe -> $(SEC_CRIT) ; + /sbin/pump -> $(SEC_CRIT) ; + /sbin/setpci -> $(SEC_CRIT) ; + /sbin/shapecfg -> $(SEC_CRIT) ; +} + + ############################### + # ## +############################### # +# # # +# System Information Programs # # +# ## +############################### +( + rulename = "System Information Programs", + severity = $(SIG_HI) +) +{ + /sbin/consoletype -> $(SEC_CRIT) ; + /sbin/kernelversion -> $(SEC_CRIT) ; + /sbin/runlevel -> $(SEC_CRIT) ; +} + + #################################### + # ## +#################################### # +# # # +# Application Information Programs # # +# ## +#################################### + +( + rulename = "Application Information Programs", + severity = $(SIG_HI) +) +{ + /sbin/genksyms -> $(SEC_CRIT) ; + #/sbin/genksyms.old -> $(SEC_CRIT) ; + /sbin/rtmon -> $(SEC_CRIT) ; +} + + ########################## + # ## +########################## # +# # # +# Shell Related Programs # # +# ## +########################## +( + rulename = "Shell Related Programs", + severity = $(SIG_HI) +) +{ + /sbin/getkey -> $(SEC_CRIT) ; + /sbin/nash -> $(SEC_CRIT) ; + /sbin/sash -> $(SEC_CRIT) ; +} + + + ################ + # ## +################ # +# # # +# OS Utilities # # +# ## +################ +( + rulename = "Operating System Utilities", + severity = $(SIG_HI) +) +{ + /bin/arch -> $(SEC_CRIT) ; + /bin/ash -> $(SEC_CRIT) ; + /bin/ash.static -> $(SEC_CRIT) ; + /bin/aumix-minimal -> $(SEC_CRIT) ; + /bin/basename -> $(SEC_CRIT) ; + /bin/cat -> $(SEC_CRIT) ; + /bin/consolechars -> $(SEC_CRIT) ; + /bin/cut -> $(SEC_CRIT) ; + /bin/date -> $(SEC_CRIT) ; + /bin/dd -> $(SEC_CRIT) ; + /bin/df -> $(SEC_CRIT) ; + /bin/dmesg -> $(SEC_CRIT) ; + /bin/doexec -> $(SEC_CRIT) ; + /bin/echo -> $(SEC_CRIT) ; + /bin/ed -> $(SEC_CRIT) ; + /bin/egrep -> $(SEC_CRIT) ; + /bin/false -> $(SEC_CRIT) ; + /bin/fgrep -> $(SEC_CRIT) ; + /bin/gawk -> $(SEC_CRIT) ; + /bin/gawk-3.1.0 -> $(SEC_CRIT) ; + /bin/gettext -> $(SEC_CRIT) ; + /bin/grep -> $(SEC_CRIT) ; + /bin/gunzip -> $(SEC_CRIT) ; + /bin/gzip -> $(SEC_CRIT) ; + /bin/hostname -> $(SEC_CRIT) ; + /bin/igawk -> $(SEC_CRIT) ; + /bin/ipcalc -> $(SEC_CRIT) ; + /bin/kill -> $(SEC_CRIT) ; + /bin/ln -> $(SEC_CRIT) ; + /bin/loadkeys -> $(SEC_CRIT) ; + /bin/login -> $(SEC_CRIT) ; + /bin/ls -> $(SEC_CRIT) ; + /bin/mail -> $(SEC_CRIT) ; + /bin/more -> $(SEC_CRIT) ; + /bin/mt -> $(SEC_CRIT) ; + /bin/mv -> $(SEC_CRIT) ; + /bin/netstat -> $(SEC_CRIT) ; + /bin/nice -> $(SEC_CRIT) ; + /bin/pgawk -> $(SEC_CRIT) ; + /bin/ps -> $(SEC_CRIT) ; + /bin/rpm -> $(SEC_CRIT) ; + /bin/sed -> $(SEC_CRIT) ; + /bin/sleep -> $(SEC_CRIT) ; + /bin/sort -> $(SEC_CRIT) ; + /bin/stty -> $(SEC_CRIT) ; + /bin/su -> $(SEC_CRIT) ; + /bin/sync -> $(SEC_CRIT) ; + /bin/tar -> $(SEC_CRIT) ; + /bin/true -> $(SEC_CRIT) ; + /bin/usleep -> $(SEC_CRIT) ; + /bin/vi -> $(SEC_CRIT) ; + /bin/zcat -> $(SEC_CRIT) ; + /bin/zsh -> $(SEC_CRIT) ; + #/bin/zsh-4.0.2 -> $(SEC_CRIT) ; + /sbin/sln -> $(SEC_CRIT) ; + /usr/bin/vimtutor -> $(SEC_CRIT) ; +} + + ############################## + # ## +############################## # +# # # +# Critical Utility Sym-Links # # +# ## +############################## +( + rulename = "Critical Utility Sym-Links", + severity = $(SIG_HI) +) +{ + #/sbin/askrunlevel -> $(SEC_CRIT) ; + /sbin/clock -> $(SEC_CRIT) ; + #/sbin/fixperm -> $(SEC_CRIT) ; + /sbin/fsck.reiserfs -> $(SEC_CRIT) ; + #/sbin/fsconf -> $(SEC_CRIT) ; + /sbin/ipfwadm-wrapper -> $(SEC_CRIT) ; + /sbin/kallsyms -> $(SEC_CRIT) ; + /sbin/ksyms -> $(SEC_CRIT) ; + /sbin/lsmod -> $(SEC_CRIT) ; + #/sbin/mailconf -> $(SEC_CRIT) ; + /sbin/mkfs.reiserfs -> $(SEC_CRIT) ; + #/sbin/modemconf -> $(SEC_CRIT) ; + /sbin/modprobe -> $(SEC_CRIT) ; + /sbin/mount.ncp -> $(SEC_CRIT) ; + /sbin/mount.ncpfs -> $(SEC_CRIT) ; + /sbin/mount.smb -> $(SEC_CRIT) ; + /sbin/mount.smbfs -> $(SEC_CRIT) ; + #/sbin/netconf -> $(SEC_CRIT) ; + /sbin/pidof -> $(SEC_CRIT) ; + /sbin/poweroff -> $(SEC_CRIT) ; + /sbin/quotaoff -> $(SEC_CRIT) ; + /sbin/raid0run -> $(SEC_CRIT) ; + /sbin/raidhotadd -> $(SEC_CRIT) ; + /sbin/raidhotgenerateerror -> $(SEC_CRIT) ; + /sbin/raidhotremove -> $(SEC_CRIT) ; + /sbin/raidstop -> $(SEC_CRIT) ; + /sbin/rdump -> $(SEC_CRIT) ; + /sbin/rdump.static -> $(SEC_CRIT) ; + /sbin/reboot -> $(SEC_CRIT) ; + /sbin/rmmod -> $(SEC_CRIT) ; + /sbin/rrestore -> $(SEC_CRIT) ; + /sbin/rrestore.static -> $(SEC_CRIT) ; + /sbin/swapoff -> $(SEC_CRIT) ; + /sbin/telinit -> $(SEC_CRIT) ; + #/sbin/userconf -> $(SEC_CRIT) ; + #/sbin/uucpconf -> $(SEC_CRIT) ; + #/sbin/vregistry -> $(SEC_CRIT) ; + /bin/awk -> $(SEC_CRIT) ; + /bin/bash2 -> $(SEC_CRIT) ; + /bin/bsh -> $(SEC_CRIT) ; + /bin/csh -> $(SEC_CRIT) ; + /bin/dnsdomainname -> $(SEC_CRIT) ; + /bin/domainname -> $(SEC_CRIT) ; + /bin/ex -> $(SEC_CRIT) ; + /bin/gtar -> $(SEC_CRIT) ; + /bin/nisdomainname -> $(SEC_CRIT) ; + /bin/red -> $(SEC_CRIT) ; + /bin/rvi -> $(SEC_CRIT) ; + /bin/rview -> $(SEC_CRIT) ; + /bin/view -> $(SEC_CRIT) ; + /bin/ypdomainname -> $(SEC_CRIT) ; +} + + + ######################### + # ## +######################### # +# # # +# Temporary directories # # +# ## +######################### +( + rulename = "Temporary directories", + recurse = false, + severity = $(SIG_LOW) +) +{ + /usr/tmp -> $(SEC_INVARIANT) ; + /var/tmp -> $(SEC_INVARIANT) ; + /tmp -> $(SEC_INVARIANT) ; +} + + ############### + # ## +############### # +# # # +# Local files # # +# ## +############### +( + rulename = "User binaries", + severity = $(SIG_MED) +) +{ + /sbin -> $(SEC_BIN) (recurse = 1) ; + /usr/bin -> $(SEC_BIN) (recurse = 1) ; + /usr/sbin -> $(SEC_BIN) (recurse = 1) ; + /usr/local/bin -> $(SEC_BIN) (recurse = 1) ; +} + +( + rulename = "Shell Binaries", + severity = $(SIG_HI) +) +{ + /bin/bash -> $(SEC_BIN) ; + /bin/ksh -> $(SEC_BIN) ; + # /bin/psh -> $(SEC_BIN) ; # No longer used? + # /bin/Rsh -> $(SEC_BIN) ; # No longer used? + /bin/sh -> $(SEC_BIN) ; + # /bin/shell -> $(SEC_SUID) ; # No longer used? + # /bin/tsh -> $(SEC_BIN) ; # No longer used? + /bin/tcsh -> $(SEC_BIN) ; + /sbin/nologin -> $(SEC_BIN) ; +} + +( + rulename = "Security Control", + severity = $(SIG_HI) +) +{ + /etc/group -> $(SEC_CRIT) ; + /etc/security -> $(SEC_CRIT) ; + #/var/spool/cron/crontabs -> $(SEC_CRIT) ; # Uncomment when this file exists +} + +#( +# rulename = "Boot Scripts", +# severity = $(SIG_HI) +#) +#{ +# /etc/rc -> $(SEC_CONFIG) ; +# /etc/rc.bsdnet -> $(SEC_CONFIG) ; +# /etc/rc.dt -> $(SEC_CONFIG) ; +# /etc/rc.net -> $(SEC_CONFIG) ; +# /etc/rc.net.serial -> $(SEC_CONFIG) ; +# /etc/rc.nfs -> $(SEC_CONFIG) ; +# /etc/rc.powerfail -> $(SEC_CONFIG) ; +# /etc/rc.tcpip -> $(SEC_CONFIG) ; +# /etc/trcfmt.Z -> $(SEC_CONFIG) ; +#} + +( + rulename = "Login Scripts", + severity = $(SIG_HI) +) +{ + /etc/bashrc -> $(SEC_CONFIG) ; + /etc/csh.cshrc -> $(SEC_CONFIG) ; + /etc/csh.login -> $(SEC_CONFIG) ; + /etc/inputrc -> $(SEC_CONFIG) ; + # /etc/tsh_profile -> $(SEC_CONFIG) ; #Uncomment when this file exists + /etc/profile -> $(SEC_CONFIG) ; +} + +# Libraries +( + rulename = "Libraries", + severity = $(SIG_MED) +) +{ + /usr/lib -> $(SEC_BIN) ; + /usr/local/lib -> $(SEC_BIN) ; +} + + + ###################################################### + # ## +###################################################### # +# # # +# Critical System Boot Files # # +# These files are critical to a correct system boot. # # +# ## +###################################################### + +( + rulename = "Critical system boot files", + severity = $(SIG_HI) +) +{ + /boot -> $(SEC_CRIT) ; + #/sbin/devfsd -> $(SEC_CRIT) ; + /sbin/grub -> $(SEC_CRIT) ; + /sbin/grub-install -> $(SEC_CRIT) ; + /sbin/grub-md5-crypt -> $(SEC_CRIT) ; + /sbin/installkernel -> $(SEC_CRIT) ; + /sbin/lilo -> $(SEC_CRIT) ; + /sbin/mkkerneldoth -> $(SEC_CRIT) ; + !/boot/System.map ; + !/boot/module-info ; + /usr/share/grub/i386-redhat/e2fs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/fat_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/ffs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/minix_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/reiserfs_stage1_5 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/stage1 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/stage2 -> $(SEC_CRIT) ; + /usr/share/grub/i386-redhat/vstafs_stage1_5 -> $(SEC_CRIT) ; + # other boot files may exist. Look for: + #/ufsboot -> $(SEC_CRIT) ; +} + ################################################## + ################################################### + # These files change every time the system boots ## + ################################################## +( + rulename = "System boot changes", + severity = $(SIG_HI) +) +{ + !/var/run/ftp.pids-all ; # Comes and goes on reboot. + !/root/.enlightenment ; + /dev/log -> $(SEC_CONFIG) ; + /dev/cua0 -> $(SEC_CONFIG) ; + # /dev/printer -> $(SEC_CONFIG) ; # Uncomment if you have a printer device + /dev/console -> $(SEC_CONFIG) -u ; # User ID may change on console login/logout. + /dev/tty1 -> $(SEC_CONFIG) ; # tty devices + /dev/tty2 -> $(SEC_CONFIG) ; # tty devices + /dev/tty3 -> $(SEC_CONFIG) ; # are extremely + /dev/tty4 -> $(SEC_CONFIG) ; # variable + /dev/tty5 -> $(SEC_CONFIG) ; + /dev/tty6 -> $(SEC_CONFIG) ; + /dev/urandom -> $(SEC_CONFIG) ; + /dev/initctl -> $(SEC_CONFIG) ; + /var/lock/subsys -> $(SEC_CONFIG) ; + #/var/lock/subsys/amd -> $(SEC_CONFIG) ; + /var/lock/subsys/anacron -> $(SEC_CONFIG) ; + /var/lock/subsys/apmd -> $(SEC_CONFIG) ; + #/var/lock/subsys/arpwatch -> $(SEC_CONFIG) ; + /var/lock/subsys/atd -> $(SEC_CONFIG) ; + /var/lock/subsys/autofs -> $(SEC_CONFIG) ; + #/var/lock/subsys/bcm5820 -> $(SEC_CONFIG) ; + #/var/lock/subsys/bgpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/bootparamd -> $(SEC_CONFIG) ; + #/var/lock/subsys/canna -> $(SEC_CONFIG) ; + /var/lock/subsys/crond -> $(SEC_CONFIG) ; + #/var/lock/subsys/cWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/dhcpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/firewall -> $(SEC_CONFIG) ; + #/var/lock/subsys/freeWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/gated -> $(SEC_CONFIG) ; + /var/lock/subsys/gpm -> $(SEC_CONFIG) ; + #/var/lock/subsys/httpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/identd -> $(SEC_CONFIG) ; + #/var/lock/subsys/innd -> $(SEC_CONFIG) ; + /var/lock/subsys/ipchains -> $(SEC_CONFIG) ; + #/var/lock/subsys/iptables -> $(SEC_CONFIG) ; + #/var/lock/subsys/ipvsadm -> $(SEC_CONFIG) ; + #/var/lock/subsys/irda -> $(SEC_CONFIG) ; + #/var/lock/subsys/iscsi -> $(SEC_CONFIG) ; + #/var/lock/subsys/isdn -> $(SEC_CONFIG) ; + #/var/lock/subsys/junkbuster -> $(SEC_CONFIG) ; + #/var/lock/subsys/kadmin -> $(SEC_CONFIG) ; + /var/lock/subsys/keytable -> $(SEC_CONFIG) ; + #/var/lock/subsys/kprop -> $(SEC_CONFIG) ; + #/var/lock/subsys/krb524 -> $(SEC_CONFIG) ; + #/var/lock/subsys/krb5kdc -> $(SEC_CONFIG) ; + /var/lock/subsys/kudzu -> $(SEC_CONFIG) ; + #/var/lock/subsys/kWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/ldap -> $(SEC_CONFIG) ; + #/var/lock/subsys/linuxconf -> $(SEC_CONFIG) ; + #/var/lock/subsys/lpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/mars_nwe -> $(SEC_CONFIG) ; + #/var/lock/subsys/mcserv -> $(SEC_CONFIG) ; + #/var/lock/subsys/mysqld -> $(SEC_CONFIG) ; + #/var/lock/subsys/named -> $(SEC_CONFIG) ; + /var/lock/subsys/netfs -> $(SEC_CONFIG) ; + /var/lock/subsys/network -> $(SEC_CONFIG) ; + #/var/lock/subsys/nfs -> $(SEC_CONFIG) ; + /var/lock/subsys/nfslock -> $(SEC_CONFIG) ; + #/var/lock/subsys/nscd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ntpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ospf6d -> $(SEC_CONFIG) ; + #/var/lock/subsys/ospfd -> $(SEC_CONFIG) ; + /var/lock/subsys/pcmcia -> $(SEC_CONFIG) ; + /var/lock/subsys/portmap -> $(SEC_CONFIG) ; + #/var/lock/subsys/postgresql -> $(SEC_CONFIG) ; + #/var/lock/subsys/pxe -> $(SEC_CONFIG) ; + #/var/lock/subsys/radvd -> $(SEC_CONFIG) ; + /var/lock/subsys/random -> $(SEC_CONFIG) ; + #/var/lock/subsys/rarpd -> $(SEC_CONFIG) ; + /var/lock/subsys/reconfig -> $(SEC_CONFIG) ; + /var/lock/subsys/rhnsd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ripd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ripngd -> $(SEC_CONFIG) ; + #/var/lock/subsys/routed -> $(SEC_CONFIG) ; + #/var/lock/subsys/rstatd -> $(SEC_CONFIG) ; + #/var/lock/subsys/rusersd -> $(SEC_CONFIG) ; + #/var/lock/subsys/rwalld -> $(SEC_CONFIG) ; + #/var/lock/subsys/rwhod -> $(SEC_CONFIG) ; + /var/lock/subsys/sendmail -> $(SEC_CONFIG) ; + #/var/lock/subsys/smb -> $(SEC_CONFIG) ; + #/var/lock/subsys/snmpd -> $(SEC_CONFIG) ; + #/var/lock/subsys/squid -> $(SEC_CONFIG) ; + /var/lock/subsys/sshd -> $(SEC_CONFIG) ; + /var/lock/subsys/syslog -> $(SEC_CONFIG) ; + #/var/lock/subsys/tux -> $(SEC_CONFIG) ; + #/var/lock/subsys/tWnn -> $(SEC_CONFIG) ; + #/var/lock/subsys/ups -> $(SEC_CONFIG) ; + #/var/lock/subsys/vncserver -> $(SEC_CONFIG) ; + #/var/lock/subsys/wine -> $(SEC_CONFIG) ; + /var/lock/subsys/xfs -> $(SEC_CONFIG) ; + /var/lock/subsys/xinetd -> $(SEC_CONFIG) ; + /var/lock/subsys/ypbind -> $(SEC_CONFIG) ; + #/var/lock/subsys/yppasswdd -> $(SEC_CONFIG) ; + #/var/lock/subsys/ypserv -> $(SEC_CONFIG) ; + #/var/lock/subsys/ypxfrd -> $(SEC_CONFIG) ; + #/var/lock/subsys/zebra -> $(SEC_CONFIG) ; + /var/run -> $(SEC_CONFIG) ; + /var/log -> $(SEC_CONFIG) ; + /etc/ioctl.save -> $(SEC_CONFIG) ; + /etc/issue.net -> $(SEC_CONFIG) -i ; # Inode number changes + /etc/issue -> $(SEC_CONFIG) ; + /etc/mtab -> $(SEC_CONFIG) -i ; # Inode number changes on any mount/unmount + /lib/modules -> $(SEC_CONFIG) ; + /etc/.pwd.lock -> $(SEC_CONFIG) ; + # /lib/modules/preferred -> $(SEC_CONFIG) ; #Uncomment when this file exists +} + +# These files change the behavior of the root account +( + rulename = "Root config files", + severity = 100 +) +{ + /root -> $(SEC_CRIT) ; # Catch all additions to /root + #/root/.Xresources -> $(SEC_CONFIG) ; + /root/.bashrc -> $(SEC_CONFIG) ; + /root/.bash_profile -> $(SEC_CONFIG) ; + /root/.bash_logout -> $(SEC_CONFIG) ; + /root/.cshrc -> $(SEC_CONFIG) ; + /root/.tcshrc -> $(SEC_CONFIG) ; + /root/Mail -> $(SEC_CONFIG) ; + #/root/mail -> $(SEC_CONFIG) ; + #/root/.amandahosts -> $(SEC_CONFIG) ; + #/root/.addressbook.lu -> $(SEC_CONFIG) ; + #/root/.addressbook -> $(SEC_CONFIG) ; + /root/.bash_history -> $(SEC_CONFIG) ; + /root/.elm -> $(SEC_CONFIG) ; + #/root/.esd_auth -> $(SEC_CONFIG) ; + /root/.gnome_private -> $(SEC_CONFIG) ; + /root/.gnome-desktop -> $(SEC_CONFIG) ; + /root/.gnome -> $(SEC_CONFIG) ; + /root/.ICEauthority -> $(SEC_CONFIG) ; + #/root/.mc -> $(SEC_CONFIG) ; + #/root/.pinerc -> $(SEC_CONFIG) ; + /root/.sawfish -> $(SEC_CONFIG) ; + /root/.Xauthority -> $(SEC_CONFIG) -i ; # Changes Inode number on login + #/root/.xauth -> $(SEC_CONFIG) ; + /root/.xsession-errors -> $(SEC_CONFIG) ; +} + + ################################ + # ## +################################ # +# # # +# Critical configuration files # # +# ## +################################ +( + rulename = "Critical configuration files", + severity = $(SIG_HI) +) +{ + #/etc/conf.linuxconf -> $(SEC_BIN) ; + /etc/crontab -> $(SEC_BIN) ; + /etc/cron.hourly -> $(SEC_BIN) ; + /etc/cron.daily -> $(SEC_BIN) ; + /etc/cron.weekly -> $(SEC_BIN) ; + /etc/cron.monthly -> $(SEC_BIN) ; + /etc/default -> $(SEC_BIN) ; + /etc/fstab -> $(SEC_BIN) ; + /etc/exports -> $(SEC_BIN) ; + /etc/group- -> $(SEC_BIN) ; # changes should be infrequent + /etc/host.conf -> $(SEC_BIN) ; + /etc/hosts.allow -> $(SEC_BIN) ; + /etc/hosts.deny -> $(SEC_BIN) ; + /etc/httpd/conf -> $(SEC_BIN) ; # changes should be infrequent + /etc/protocols -> $(SEC_BIN) ; + /etc/services -> $(SEC_BIN) ; + /etc/rc.d/init.d -> $(SEC_BIN) ; + /etc/rc.d -> $(SEC_BIN) ; + /etc/mail.rc -> $(SEC_BIN) ; + /etc/modules.conf -> $(SEC_BIN) ; + /etc/motd -> $(SEC_BIN) ; + /etc/named.conf -> $(SEC_BIN) ; + /etc/passwd -> $(SEC_CONFIG) ; + /etc/passwd- -> $(SEC_CONFIG) ; + /etc/profile.d -> $(SEC_BIN) ; + /var/lib/nfs/rmtab -> $(SEC_BIN) ; + /usr/sbin/fixrmtab -> $(SEC_BIN) ; + /etc/rpc -> $(SEC_BIN) ; + /etc/sysconfig -> $(SEC_BIN) ; + /etc/samba/smb.conf -> $(SEC_CONFIG) ; + #/etc/gettydefs -> $(SEC_BIN) ; + /etc/nsswitch.conf -> $(SEC_BIN) ; + /etc/yp.conf -> $(SEC_BIN) ; + /etc/hosts -> $(SEC_CONFIG) ; + /etc/xinetd.conf -> $(SEC_CONFIG) ; + /etc/inittab -> $(SEC_CONFIG) ; + /etc/resolv.conf -> $(SEC_CONFIG) ; + /etc/syslog.conf -> $(SEC_CONFIG) ; +} + + #################### + # ## +#################### # +# # # +# Critical devices # # +# ## +#################### +( + rulename = "Critical devices", + severity = $(SIG_HI), + recurse = false +) +{ + /dev/kmem -> $(Device) ; + /dev/mem -> $(Device) ; + /dev/null -> $(Device) ; + /dev/zero -> $(Device) ; + /proc/devices -> $(Device) ; + /proc/net -> $(Device) ; + /proc/sys -> $(Device) ; + /proc/cpuinfo -> $(Device) ; + /proc/modules -> $(Device) ; + /proc/mounts -> $(Device) ; + /proc/dma -> $(Device) ; + /proc/filesystems -> $(Device) ; + /proc/pci -> $(Device) ; + /proc/interrupts -> $(Device) ; + /proc/driver/rtc -> $(Device) ; + /proc/ioports -> $(Device) ; + #/proc/scsi -> $(Device) ; + /proc/kcore -> $(Device) ; + /proc/self -> $(Device) ; + /proc/kmsg -> $(Device) ; + /proc/stat -> $(Device) ; + /proc/ksyms -> $(Device) ; + /proc/loadavg -> $(Device) ; + /proc/uptime -> $(Device) ; + /proc/locks -> $(Device) ; + /proc/version -> $(Device) ; + /proc/mdstat -> $(Device) ; + /proc/meminfo -> $(Device) ; + /proc/cmdline -> $(Device) ; + /proc/misc -> $(Device) ; +} + +# Rest of critical system binaries +( + rulename = "OS executables and libraries", + severity = $(SIG_HI) +) +{ + /bin -> $(SEC_BIN) ; + /lib -> $(SEC_BIN) ; +} + +#============================================================================= +# +# Copyright 2000 Tripwire, Inc. Tripwire is a registered trademark of Tripwire, +# Inc. in the United States and other countries. All rights reserved. +# +# Linux is a registered trademark of Linus Torvalds. +# +# UNIX is a registered trademark of The Open Group. +# +#============================================================================= +# +# Permission is granted to make and distribute verbatim copies of this document +# provided the copyright notice and this permission notice are preserved on all +# copies. +# +# Permission is granted to copy and distribute modified versions of this +# document under the conditions for verbatim copying, provided that the entire +# resulting derived work is distributed under the terms of a permission notice +# identical to this one. +# +# Permission is granted to copy and distribute translations of this document +# into another language, under the above conditions for modified versions, +# except that this permission notice may be stated in a translation approved by +# Tripwire, Inc. +# +# DCM +# +# $Id: twpol-GENERIC.txt,v 1.1 2003/06/08 02:00:06 pherman Exp $ +# diff --git a/policy/twpol-Linux.txt b/policy/twpol-Linux.txt new file mode 100644 index 0000000..9e1d983 --- /dev/null +++ b/policy/twpol-Linux.txt @@ -0,0 +1,355 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Policy file for Red Hat Linux # # +# ## +############################################################################## + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# Manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + + ############################################################################## + # Predefined Variables # +############################################################################## +# +# Property Masks +# +# - ignore the following properties +# + check the following properties +# +# a access timestamp (mutually exclusive with +CMSH) +# b number of blocks allocated +# c inode creation/modification timestamp +# d ID of device on which inode resides +# g group id of owner +# i inode number +# l growing files (logfiles for example) +# m modification timestamp +# n number of links +# p permission and file mode bits +# r ID of device pointed to by inode (valid only for device objects) +# s file size +# t file type +# u user id of owner +# +# C CRC-32 hash +# H HAVAL hash +# M MD5 hash +# S SHA hash +# +############################################################################## + +Device = +pugsdr-intlbamcCMSH ; +Dynamic = +pinugtd-srlbamcCMSH ; +Growing = +pinugtdl-srbamcCMSH ; +IgnoreAll = -pinugtsdrlbamcCMSH ; +IgnoreNone = +pinugtsdrbamcCMSH-l ; +ReadOnly = +pinugtsdbmCM-rlacSH ; +Temporary = +pugt ; + +@@section FS + + ######################################## + # ## +######################################## # +# # # +# Tripwire Binaries and Data Files # # +# ## +######################################## + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", +) +{ + $(TWBIN)/siggen -> $(ReadOnly) ; + $(TWBIN)/tripwire -> $(ReadOnly) ; + $(TWBIN)/twadmin -> $(ReadOnly) ; + $(TWBIN)/twprint -> $(ReadOnly) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(Dynamic) -i ; + $(TWPOL)/tw.pol -> $(ReadOnly) -i ; + $(TWPOL)/tw.cfg -> $(ReadOnly) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(ReadOnly) ; + $(TWSKEY)/site.key -> $(ReadOnly) ; + + # don't scan the individual reports + $(TWREPORT) -> $(Dynamic) (recurse=0) ; +} + + ################################################ + # ## +################################################ # +# # # +# RPM Checksum Files # # +# ## +################################################ +( + rulename = "RPM Checksum Files", +) +{ + /var/lib/rpm -> $(ReadOnly); + /var/lib/rpm/__db.001 -> $(Dynamic) ; + /var/lib/rpm/__db.002 -> $(Dynamic) ; + /var/lib/rpm/__db.003 -> $(Dynamic) ; +} + + ################################################ + # ## +################################################ # +# # # +# Global Configuration Files (/etc/) # # +# ## +################################################ +( + rulename = "Global Configuration Files", +) +{ + /etc -> $(IgnoreNone) -SHa ; + /etc/adjtime -> $(Dynamic) ; + /etc/aliases.db -> $(Dynamic) ; + /etc/bashrc -> $(Dynamic) ; + /etc/csh.cshrc -> $(Dynamic) ; + /etc/csh.login -> $(Dynamic) ; + /etc/mail/statistics -> $(Growing) ; + /etc/profile -> $(Dynamic) -i ; + /etc/mtab -> $(Dynamic) -i ; + /etc/rc.d -> $(IgnoreNone) -SHa ; + /etc/sysconfig -> $(IgnoreNone) -SHa ; + /etc/sysconfig/hwconf -> $(Dynamic) -m ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Boot Files and Mount Points # # +# ## +################################################ +( + rulename = "OS Boot Files and Mount Points", +) +{ + /boot -> $(ReadOnly) ; + /cdrom -> $(Dynamic) ; + /floppy -> $(Dynamic) ; + /mnt -> $(Dynamic) ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Devices and Misc Directories # # +# ## +################################################ +( + rulename = "OS Devices and Misc Directories", +) +{ + /dev -> $(Device) ; + /initrd -> $(Dynamic) ; + /opt -> $(Dynamic) ; + /lost+found -> $(Dynamic) ; + /var/lost+found -> $(Dynamic) ; + /home/lost+found -> $(Dynamic) ; + !/dev/pts ; # Ignore this file + !/dev/shm ; # Ignore this file +} + + ################################################ + # ## +################################################ # +# # # +# OS Binaries and Libraries # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", +) +{ + /bin -> $(ReadOnly) ; + /lib -> $(ReadOnly) ; + /sbin -> $(ReadOnly) ; + /usr/bin -> $(ReadOnly) ; + /usr/lib -> $(ReadOnly) ; + /usr/libexec -> $(ReadOnly) ; + /usr/sbin -> $(ReadOnly) ; + /usr/X11R6/lib -> $(ReadOnly) ; +} + ################################################ + # ## +################################################ # +# # # +# User Binaries and Libraries # # +# ## +################################################ +( + rulename = "User Binaries and Libraries", +) +{ + !/home/local; + /usr/local -> $(ReadOnly) ; + /usr/local/bin -> $(ReadOnly) ; + /usr/local/doc -> $(ReadOnly) ; + /usr/local/etc -> $(ReadOnly) ; + /usr/local/games -> $(ReadOnly) ; + /usr/local/include -> $(ReadOnly) ; + /usr/local/lib -> $(ReadOnly) ; + /usr/local/libexec -> $(ReadOnly) ; + /usr/local/man -> $(ReadOnly) ; + /usr/local/sbin -> $(ReadOnly) ; + /usr/local/share -> $(ReadOnly) ; + /usr/local/src -> $(ReadOnly) ; + /usr/local/sysinfo -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Root Directory and Files # # +# ## +################################################ +( + rulename = "Root Directory and Files", +) +{ + /root -> $(IgnoreNone) -SHa ; + /root/.bashrc -> $(Dynamic) ; + /root/.bash_history -> $(Dynamic) ; + #/root/.bash_logout -> $(Dynamic) ; + /root/.bash_profile -> $(Dynamic) ; + /root/.cshrc -> $(Dynamic) ; + #/root/.enlightenment -> $(Dynamic) ; + #/root/.esd-auth -> $(Dynamic) ; + !/root/.gconf ; + !/root/.gconfd ; + #/root/.gnome -> $(Dynamic) ; + #/root/.gnome-desktop -> $(Dynamic) ; + #/root/.gnome2 -> $(Dynamic) ; + #/root/.gtkrc -> $(Dynamic) ; + #/root/.gtkrc-1.2-gnome2 -> $(Dynamic) ; + #/root/.metacity -> $(Dynamic) ; + #/root/.nautilus -> $(Dynamic) ; + #/root/.rhn-applet.conf -> $(Dynamic) ; + #/root/.tcshrc -> $(Dynamic) ; + #/root/.xauth -> $(Dynamic) ; + #/root/.ICEauthority -> $(Dynamic) ; + #/root/.Xauthority -> $(Dynamic) -i ; + #/root/.Xresources -> $(Dynamic) ; +} + + ################################################ + # ## +################################################ # +# # # +# Temporary Directories # # +# ## +################################################ +( + rulename = "Temporary Directories", +) +{ + /usr/tmp -> $(Temporary) ; + /var/tmp -> $(Temporary) ; + /tmp -> $(Temporary) ; + #/tmp/.fam-socket -> $(Temporary) ; + #/tmp/.ICE-unix -> $(Temporary) ; + #/tmp/.X11-unix -> $(Temporary) ; + !/tmp/orbit-root ; +} + + ################################################ + # ## +################################################ # +# # # +# System Boot Changes # # +# ## +################################################ +( + rulename = "System Boot Changes", +) +{ + /.autofsck -> $(Dynamic) -m ; + /var/cache/man/whatis -> $(Growing) ; + /var/lib/logrotate.status -> $(Growing) ; + #/var/lib/nfs/statd -> $(Growing) ; + !/var/lib/random-seed ; + #/var/lib/slocate/slocate.db -> $(Growing) -is ; + /var/lock/subsys -> $(Dynamic) -i ; + /var/log -> $(Growing) -i ; + !/var/log/sa; + !/var/log/cisco; + /var/run -> $(Dynamic) -i ; + /etc/cron.daily -> $(Growing); + /etc/cron.weekly -> $(Growing); + /etc/cron.monthly -> $(Growing); + /var/spool/mail -> $(Growing); +} + + ################################################ + # ## +################################################ # +# # # +# Monitor Filesystems # # +# ## +################################################ +( + rulename = "Monitor Filesystems", +) +{ + / -> $(ReadOnly) ; + /home -> $(ReadOnly) ; # Modify as needed + /usr -> $(ReadOnly) ; + /var -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Proc Filesystem # # +# ## +################################################ +( + rulename = "Proc Filesystem", +) +{ + !/proc ; # Ignore most of this directory +} diff --git a/policy/twpol-OpenBSD.txt b/policy/twpol-OpenBSD.txt new file mode 100644 index 0000000..1591119 --- /dev/null +++ b/policy/twpol-OpenBSD.txt @@ -0,0 +1,292 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Policy file for OpenBSD 3.5 # # +# May 20, 2003 # # +# ## +############################################################################## + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + +@@section GLOBAL +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + + ############################################################################## + # Predefined Variables # +############################################################################## +# +# Property Masks +# +# - ignore the following properties +# + check the following properties +# +# a access timestamp (mutually exclusive with +CMSH) +# b number of blocks allocated +# c inode creation/modification timestamp +# d ID of device on which inode resides +# g group id of owner +# i inode number +# l growing files (logfiles for example) +# m modification timestamp +# n number of links +# p permission and file mode bits +# r ID of device pointed to by inode (valid only for device objects) +# s file size +# t file type +# u user id of owner +# +# C CRC-32 hash +# H HAVAL hash +# M MD5 hash +# S SHA hash +# +############################################################################## + +Device = +pugsdr-intlbamcCMSH ; +Dynamic = +pinugtd-srlbamcCMSH ; +Growing = +pinugtdl-srbamcCMSH ; +IgnoreAll = -pinugtsdrlbamcCMSH ; +IgnoreNone = +pinugtsdrbamcCMSH-l ; +ReadOnly = +pinugtsdbmCM-rlacSH ; +Temporary = +pugt ; + +@@section FS + + ######################################## + # ## +######################################## # +# # # +# Tripwire Binaries and Data Files # # +# ## +######################################## + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", +) +{ + $(TWBIN)/siggen -> $(ReadOnly) ; + $(TWBIN)/tripwire -> $(ReadOnly) ; + $(TWBIN)/twadmin -> $(ReadOnly) ; + $(TWBIN)/twprint -> $(ReadOnly) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(Dynamic) -i ; + $(TWPOL)/tw.pol -> $(ReadOnly) -i ; + $(TWPOL)/tw.cfg -> $(ReadOnly) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(ReadOnly) ; + $(TWSKEY)/site.key -> $(ReadOnly) ; + + # don't scan the individual reports + $(TWREPORT) -> $(Dynamic) (recurse=0) ; + + # In this configuration /usr/local is a symbolic link to /home/local. + # We want to ignore the following directories since they are already + # scanned using the real directory or mount point. Otherwise we see + # duplicates in the reports. + + !/home/local ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Boot and Configuration Files # # +# ## +################################################ +( + rulename = "OS Boot and Configuration Files", +) +{ + /boot -> $(ReadOnly) ; + /bsd -> $(ReadOnly) ; + /etc -> $(IgnoreNone) -SHa ; +} + + ################################################### + # ## +################################################### # +# # # +# Mount Points # # +# ## +################################################### +( + rulename = "Mount Points", +) +{ + / -> $(ReadOnly) ; + /cdrom -> $(Dynamic) ; + /floppy -> $(Dynamic) ; + /home -> $(ReadOnly) ; # Modify as needed + /mnt -> $(Dynamic) ; + /usr -> $(ReadOnly) ; + /var -> $(ReadOnly) ; +} + + ################################################### + # ## +################################################### # +# # # +# Misc Top-Level Directories # # +# ## +################################################### +( + rulename = "Misc Top-Level Directories", +) +{ + /altroot -> $(Dynamic) ; + /stand -> $(Dynamic) ; +} + + ################################################ + # ## +################################################ # +# # # +# System Devices # # +# ## +################################################ +( + rulename = "System Devices", +) +{ + /dev -> $(Device) ; + /dev/fd -> $(Device) ; + /var/cron/tabs/.sock -> $(Device) ; + /var/empty/dev/log -> $(Device) ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Binaries and Libraries # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", +) +{ + /bin -> $(ReadOnly) ; + /sbin -> $(ReadOnly) ; + /usr/bin -> $(ReadOnly) ; + /usr/lib -> $(ReadOnly) ; + /usr/libexec -> $(ReadOnly) ; + /usr/sbin -> $(ReadOnly) ; + /usr/X11R6/bin -> $(ReadOnly) ; + /usr/X11R6/lib -> $(ReadOnly) ; +} + ################################################ + # ## +################################################ # +# # # +# Usr Local Files # # +# ## +################################################ +#OK( + #OKrulename = "Usr Local Files", +#OK) +#OK{ + #OK/usr/local -> $(ReadOnly) ; + #OK/usr/local/bin -> $(ReadOnly) ; + #OK/usr/local/doc -> $(ReadOnly) ; + #OK/usr/local/etc -> $(ReadOnly) ; + #OK/usr/local/include -> $(ReadOnly) ; + #OK/usr/local/info -> $(ReadOnly) ; + #OK/usr/local/lib -> $(ReadOnly) ; + #OK/usr/local/libdata -> $(ReadOnly) ; + #OK/usr/local/libexec -> $(ReadOnly) ; + #OK/usr/local/man -> $(ReadOnly) ; + #OK/usr/local/sbin -> $(ReadOnly) ; + #OK/usr/local/share -> $(ReadOnly) ; + #OK/usr/local/src -> $(ReadOnly) ; +#OK} + + ################################################ + # ## +################################################ # +# # # +# Root Directory and Files # # +# ## +################################################ +( + rulename = "Root Directory and Files", +) +{ + /root -> $(IgnoreNone) -SHa ; + /root/.cshrc -> $(Dynamic) ; + /root/.profile -> $(Dynamic) ; +} + + ################################################ + # ## +################################################ # +# # # +# Temporary Directories # # +# ## +################################################ +( + rulename = "Temporary Directories", +) +{ + /tmp -> $(Temporary) ; + /var/tmp -> $(Temporary) ; +} + + ################################################ + # ## +################################################ # +# # # +# System and Boot Changes # # +# ## +################################################ +( + rulename = "System and Boot Changes", +) +{ + /var/backups -> $(Dynamic) -i ; + /var/db/host.random -> $(ReadOnly) -mCM ; + /var/cron -> $(Growing) -i ; + /var/log -> $(Growing) -i ; + /var/run -> $(Dynamic) -i ; + /var/mail -> $(Growing) ; + /var/msgs/bounds -> $(ReadOnly) -smbCM ; + /var/spool/clientmqueue -> $(Temporary) ; + /var/spool/mqueue -> $(Temporary) ; +} + +# +# $Id: twpol-OpenBSD.txt,v 1.2 2004/05/14 21:56:21 pherman Exp $ +# diff --git a/policy/twpol-SunOS.txt b/policy/twpol-SunOS.txt new file mode 100644 index 0000000..338adfb --- /dev/null +++ b/policy/twpol-SunOS.txt @@ -0,0 +1,314 @@ + ############################################################################## + # ## +############################################################################## # +# # # +# Policy file for Solaris 8 # # +# ## +############################################################################## + + ############################################################################## + # ## +############################################################################## # +# # # +# Global Variable Definitions # # +# # # +# These are defined at install time by the installation script. You may # # +# manually edit these if you are using this file directly and not from the # # +# installation script itself. # # +# ## +############################################################################## + + +@@section GLOBAL +TWROOT=; +TWBIN=; +TWPOL=; +TWDB=; +TWSKEY=; +TWLKEY=; +TWREPORT=; +HOSTNAME=; + + + ############################################################################## + # Predefined Variables # +############################################################################## +# +# Property Masks +# +# - ignore the following properties +# + check the following properties +# +# a access timestamp (mutually exclusive with +CMSH) +# b number of blocks allocated +# c inode creation/modification timestamp +# d ID of device on which inode resides +# g group id of owner +# i inode number +# l growing files (logfiles for example) +# m modification timestamp +# n number of links +# p permission and file mode bits +# r ID of device pointed to by inode (valid only for device objects) +# s file size +# t file type +# u user id of owner +# +# C CRC-32 hash +# H HAVAL hash +# M MD5 hash +# S SHA hash +# +############################################################################## + +Device = +pugsdr-intlbamcCMSH ; +Dynamic = +pinugtd-srlbamcCMSH ; +Growing = +pinugtdl-srbamcCMSH ; +IgnoreAll = -pinugtsdrlbamcCMSH ; +IgnoreNone = +pinugtsdrbamcCMSH-l ; +ReadOnly = +pinugtsdbmCM-rlacSH ; +Temporary = +pugt ; + +@@section FS + + ######################################## + # ## +######################################## # +# # # +# Tripwire Binaries and Data Files # # +# ## +######################################## + +# Tripwire Binaries +( + rulename = "Tripwire Binaries", +) +{ + $(TWBIN)/siggen -> $(ReadOnly) ; + $(TWBIN)/tripwire -> $(ReadOnly) ; + $(TWBIN)/twadmin -> $(ReadOnly) ; + $(TWBIN)/twprint -> $(ReadOnly) ; +} + +# Tripwire Data Files - Configuration Files, Policy Files, Keys, Reports, Databases +( + rulename = "Tripwire Data Files", +) +{ + # NOTE: We remove the inode attribute because when Tripwire creates a backup, + # it does so by renaming the old file and creating a new one (which will + # have a new inode number). Inode is left turned on for keys, which shouldn't + # ever change. + + # NOTE: The first integrity check triggers this rule and each integrity check + # afterward triggers this rule until a database update is run, since the + # database file does not exist before that point. + + $(TWDB) -> $(Dynamic) -i ; + $(TWPOL)/tw.pol -> $(ReadOnly) -i ; + $(TWPOL)/tw.cfg -> $(ReadOnly) -i ; + $(TWLKEY)/$(HOSTNAME)-local.key -> $(ReadOnly) ; + $(TWSKEY)/site.key -> $(ReadOnly) ; + + # don't scan the individual reports + $(TWREPORT) -> $(Dynamic) (recurse=0) ; + + # In this configuration /usr/local is a symbolic link to /home/local. + # We want to ignore the following directories since they are already + # scanned using the real directory or mount point. Otherwise we see + # duplicates in the reports. + + !/home/local ; # Ignore since /home already scanned +} + + ################################################ + # ## +################################################ # +# # # +# OS Boot and Configuration Files # # +# ## +################################################ +( + rulename = "OS Boot and Configuration Files", +) +{ + /etc -> $(IgnoreNone) -SHa ; + /kernel -> $(ReadOnly) ; +} + + ################################################### + # ## +################################################### # +# # # +# Mount Points # # +# ## +################################################### +( + rulename = "Mount Points", +) +{ + / -> $(ReadOnly) ; + /cdrom -> $(Dynamic) ; + /home -> $(ReadOnly) ; + /mnt -> $(Dynamic) ; + /usr -> $(ReadOnly) ; + /var -> $(ReadOnly) ; + /opt -> $(ReadOnly) ; +} + + ################################################### + # ## +################################################### # +# # # +# Misc Top-Level Directories # # +# ## +################################################### +( + rulename = "Misc Top-Level Directories", +) +{ + /lost+found -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# System Devices # # +# ## +################################################ +( + rulename = "System Devices", +) +{ + /dev -> $(Device) ; + /devices -> $(Device) ; +} + + ################################################ + # ## +################################################ # +# # # +# OS Binaries and Libraries # # +# ## +################################################ +( + rulename = "OS Binaries and Libraries", +) +{ + /sbin -> $(ReadOnly) ; + /usr/bin -> $(ReadOnly) ; + /usr/lib -> $(ReadOnly) ; + /usr/sbin -> $(ReadOnly) ; + /usr/openwin/bin -> $(ReadOnly) ; + /usr/openwin/lib -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Root Directory and Files # # +# ## +################################################ +( + rulename = "Root Directory and Files", +) +{ + ! /.netscape/cache ; + /.bash_history -> $(ReadOnly) -smbCM; + /.sh_history -> $(Dynamic) ; + /.Xauthority -> $(ReadOnly) ; +} + + ################################################ + # ## +################################################ # +# # # +# Temporary Directories # # +# ## +################################################ +( + rulename = "Temporary Directories", +) +{ + /tmp -> $(Temporary) ; + /var/tmp -> $(Temporary) ; +} + + ################################################ + # ## +################################################ # +# # # +# System Doors and Misc Mounts # # +# ## +################################################ +( + rulename = "System Doors and Misc Mounts", +) +{ + !/etc/mnttab ; + !/etc/.name_service_door ; + !/etc/sysevent/syseventconfd_event_service ; + !/etc/sysevent/sysevent_door ; + !/etc/sysevent/piclevent_door ; + !/dev/fd ; + !/net ; + !/proc ; + !/var/run ; + !/var/run/syslog_door ; + !/vol ; + !/xfn ; + +} + + ################################################ + # ## +################################################ # +# # # +# System FIFOs # # +# ## +################################################ +( + rulename = "System FIFOs", +) +{ + !/etc/cron.d/FIFO ; + !/etc/initpipe ; + !/etc/saf/_cmdpipe ; + !/etc/saf/_sacpipe ; + !/etc/saf/zsmon/_pmpipe ; + !/etc/utmppipe ; + !/var/spool/lp/fifos/FIFO ; + !/tmp/.removable ; + !/tmp/.X11-pipe/X0 ; +} + + ################################################ + # ## +################################################ # +# # # +# System and Boot Changes # # +# ## +################################################ +( + rulename = "System and Boot Changes", +) +{ + /etc/.pwd.lock -> $(ReadOnly) -cm; + /etc/coreadm.conf -> $(ReadOnly) -cm; + /var/adm -> $(Growing) -i; + #/var/backups -> $(Dynamic) -i ; + /var/cron/log -> $(Growing) -i ; + #/var/db/host.random -> $(ReadOnly) -mCM ; + #/var/db/locate.database -> $(ReadOnly) -misCM ; + /var/log -> $(Growing) -i ; + #/var/run -> $(Dynamic) -i ; + #/var/mail -> $(Growing) ; + #/var/msgs/bounds -> $(ReadOnly) -smbCM ; + !/var/sendmail ; + !/var/spool/clientmqueue ; + !/var/spool/mqueue ; + #!/var/tmp/vi.recover ; # perl script periodically removes this + +} diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..05b233d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = cryptlib core db fco fs tw twcrypto twparser util +SUBDIRS+= twprint twadmin siggen tripwire diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..97d759c --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,445 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +SUBDIRS = cryptlib core db fco fs tw twcrypto twparser util twprint twadmin siggen tripwire +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || mkdir "$(distdir)/$$subdir" \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="../$(top_distdir)" \ + distdir="../$(distdir)/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-recursive distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/buildnum.bat b/src/buildnum.bat new file mode 100644 index 0000000..b45a8f0 --- /dev/null +++ b/src/buildnum.bat @@ -0,0 +1,2 @@ +set BLDLBL=Build_.2 +set BLDNUM=.2 diff --git a/src/buildnum.h b/src/buildnum.h new file mode 100644 index 0000000..c33dd90 --- /dev/null +++ b/src/buildnum.h @@ -0,0 +1,2 @@ +#define BUILD_NUM _T("2") + diff --git a/src/buildnum.h~ b/src/buildnum.h~ new file mode 100644 index 0000000..44f5cfa --- /dev/null +++ b/src/buildnum.h~ @@ -0,0 +1,2 @@ +#define BUILD_NUM _T("1") + diff --git a/src/buildnum.txt b/src/buildnum.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/src/buildnum.txt @@ -0,0 +1 @@ +1 diff --git a/src/buildnuminc.pl b/src/buildnuminc.pl new file mode 100755 index 0000000..47b1881 --- /dev/null +++ b/src/buildnuminc.pl @@ -0,0 +1,42 @@ +############################################################################### +# buildnuminc.pl +# +# Open the file 'buildnum.h', search for the line '#define BUILD_NUM "DDD"' (where +# DDD is a decimal integer), increment DDD, re-save the "buildnum.h" with +# the new build number +# +############################################################################### + +$filename = 'buildnum.h'; +$textname = 'buildnum.txt'; +$batname = 'buildnum.bat'; +$project = $ENV{"PROPROJ"}; + +open (TEXT, "<$textname") || die "Unable to open text file containing current build number!\n"; + +while () { + $curver = $_; +} + +print "$curver\n"; + +if ($curver !="") { + $newbuildnum = $curver + 1; +}; + +$verstring = "$project.$newbuildnum"; +print ("Incrementing Project Build Number to: $verstring\n"); +close (TEXT); + +open (HEADER, ">$filename"); +print (HEADER "#define BUILD_NUM _T(\"$newbuildnum\")\n\n"); +close (HEADER); + +open (TEXT, ">$textname"); +print (TEXT "$newbuildnum\n"); +close (TEXT); + +open (BAT, ">$batname"); +print (BAT "set BLDLBL=Build_$verstring\n"); +print (BAT "set BLDNUM=$verstring\n"); +close (BAT); diff --git a/src/check_st.pl b/src/check_st.pl new file mode 100755 index 0000000..6f5df41 --- /dev/null +++ b/src/check_st.pl @@ -0,0 +1,105 @@ +############################################################################### +# check_st.pl +# +# created 26 may 1999 mdb +# +# Purpose: +# This script verifies that all of the string refrenced in a tripwire string +# table header file has a corresponding entry in the .cpp file +# +# Usage: +# Run from the root Tripwire directory. set PKGS to the package names that you +# want to check. +# +# TODO: gracefully handle packages with no string table +# TODO: handle commented out blocks in cpp files. +# +@PKGS = ( "core", "fco", "tw", "fs", "ntfs", + "ntreg", "siggen", "tripwire", "twadmin", "twprint" ); + +##----------------------------------------------------------------------------- +## execute main +##----------------------------------------------------------------------------- +sub main; +main(); +exit 0; + +##----------------------------------------------------------------------------- +## make_string_list +## +## opens the string header file and retrieves all of the string enums +## (identified by lines starting with \s*STR_) and returns them in a list +## +## Parameters: +## package name (ie -- core) +##----------------------------------------------------------------------------- +sub make_string_list +{ + my $pkg_name = shift( @_ ); + my $header_name = "${pkg_name}/${pkg_name}strings.h"; + my @rtn_list; + open( IN, "<$header_name" ) || die "Unable to open $header_name\n"; + + while( ) + { + if( /^\s*(STR_[a-zA-Z0-9_]+)/ ) + { + push( @rtn_list, $1 ); + } + } + close( IN ); + + return @rtn_list; +} + +##----------------------------------------------------------------------------- +## verify_string_list +## +## takes as input a list of string identifiers, opens the string cpp +## file and makes sure that all strings in the list appear in that file. +## +## Limitation: +## can't tell whether entries in the cpp file are commented out. +##----------------------------------------------------------------------------- +sub verify_string_list +{ + my $pkg_name = shift( @_ ); + my @str_list = @_; + my $cpp_name = "${pkg_name}/${pkg_name}strings.cpp"; + my @cpp_lines; + my $result; + + # first, load the entire cpp file into an array... + # + open( IN, "<$cpp_name" ) || die "Unable to open $cpp_name\n"; + while( ) + { + push( @cpp_lines, $_ ); + } + + # now, iterate through the string list, looking for each + # string in the cpp file. + # + foreach $str (@str_list) + { + $result = grep( /$str/, @cpp_lines ); + if( $result == 0 ) + { + print "$str is missing from $pkg_name string table!\n"; + } + } +} + +##----------------------------------------------------------------------------- +## main +##----------------------------------------------------------------------------- +sub main +{ + my @str_list; + foreach $pkg (@PKGS) + { + print "\n*** Processing $pkg ***\n"; + @str_list = make_string_list( $pkg ); + verify_string_list( $pkg, @str_list ); + } +} \ No newline at end of file diff --git a/src/core/Makefile.am b/src/core/Makefile.am new file mode 100644 index 0000000..a06de74 --- /dev/null +++ b/src/core/Makefile.am @@ -0,0 +1,27 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libcore.a +libcore_a_SOURCES = \ + file_unix.cpp unixfsservices.cpp \ + charutil_t.cpp displayencoder_t.cpp archive.cpp charutil.cpp \ + cmdlineparser.cpp codeconvert.cpp core.cpp coreerrors.cpp \ + corestrings.cpp crc32.cpp debug.cpp displayencoder.cpp \ + displayutil.cpp error.cpp errorbucketimpl.cpp errortable.cpp \ + errorutil.cpp fileerror.cpp fileheader.cpp fsservices.cpp \ + growheap.cpp hashtable.cpp haval.cpp msystem.cpp ntmbs.cpp \ + objectpool.cpp refcountobj.cpp serializable.cpp serializer.cpp \ + serializerimpl.cpp serializerutil.cpp serstring.cpp \ + srefcountobj.cpp srefcounttbl.cpp stdcore.cpp stringutil.cpp \ + timebomb.cpp timeconvert.cpp tw_signal.cpp twlimits.cpp twlocale.cpp \ + unixexcept.cpp usernotify.cpp usernotifystdout.cpp utf8.cpp \ + wchar16.cpp + +libcore_a_LIBADD = @CORE_CRYPT_O@ +libcore_a_DEPENDENCIES = @CORE_CRYPT_O@ + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libcore_a_OBJECTS) $(libcore_a_LIBADD) diff --git a/src/core/Makefile.in b/src/core/Makefile.in new file mode 100644 index 0000000..29590b3 --- /dev/null +++ b/src/core/Makefile.in @@ -0,0 +1,427 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libcore_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/core +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libcore_a_AR = $(AR) $(ARFLAGS) +am_libcore_a_OBJECTS = file_unix.$(OBJEXT) unixfsservices.$(OBJEXT) \ + charutil_t.$(OBJEXT) displayencoder_t.$(OBJEXT) \ + archive.$(OBJEXT) charutil.$(OBJEXT) cmdlineparser.$(OBJEXT) \ + codeconvert.$(OBJEXT) core.$(OBJEXT) coreerrors.$(OBJEXT) \ + corestrings.$(OBJEXT) crc32.$(OBJEXT) debug.$(OBJEXT) \ + displayencoder.$(OBJEXT) displayutil.$(OBJEXT) error.$(OBJEXT) \ + errorbucketimpl.$(OBJEXT) errortable.$(OBJEXT) \ + errorutil.$(OBJEXT) fileerror.$(OBJEXT) fileheader.$(OBJEXT) \ + fsservices.$(OBJEXT) growheap.$(OBJEXT) hashtable.$(OBJEXT) \ + haval.$(OBJEXT) msystem.$(OBJEXT) ntmbs.$(OBJEXT) \ + objectpool.$(OBJEXT) refcountobj.$(OBJEXT) \ + serializable.$(OBJEXT) serializer.$(OBJEXT) \ + serializerimpl.$(OBJEXT) serializerutil.$(OBJEXT) \ + serstring.$(OBJEXT) srefcountobj.$(OBJEXT) \ + srefcounttbl.$(OBJEXT) stdcore.$(OBJEXT) stringutil.$(OBJEXT) \ + timebomb.$(OBJEXT) timeconvert.$(OBJEXT) tw_signal.$(OBJEXT) \ + twlimits.$(OBJEXT) twlocale.$(OBJEXT) unixexcept.$(OBJEXT) \ + usernotify.$(OBJEXT) usernotifystdout.$(OBJEXT) utf8.$(OBJEXT) \ + wchar16.$(OBJEXT) +libcore_a_OBJECTS = $(am_libcore_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libcore_a_SOURCES) +DIST_SOURCES = $(libcore_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libcore.a +libcore_a_SOURCES = \ + file_unix.cpp unixfsservices.cpp \ + charutil_t.cpp displayencoder_t.cpp archive.cpp charutil.cpp \ + cmdlineparser.cpp codeconvert.cpp core.cpp coreerrors.cpp \ + corestrings.cpp crc32.cpp debug.cpp displayencoder.cpp \ + displayutil.cpp error.cpp errorbucketimpl.cpp errortable.cpp \ + errorutil.cpp fileerror.cpp fileheader.cpp fsservices.cpp \ + growheap.cpp hashtable.cpp haval.cpp msystem.cpp ntmbs.cpp \ + objectpool.cpp refcountobj.cpp serializable.cpp serializer.cpp \ + serializerimpl.cpp serializerutil.cpp serstring.cpp \ + srefcountobj.cpp srefcounttbl.cpp stdcore.cpp stringutil.cpp \ + timebomb.cpp timeconvert.cpp tw_signal.cpp twlimits.cpp twlocale.cpp \ + unixexcept.cpp usernotify.cpp usernotifystdout.cpp utf8.cpp \ + wchar16.cpp + +libcore_a_LIBADD = @CORE_CRYPT_O@ +libcore_a_DEPENDENCIES = @CORE_CRYPT_O@ +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/core/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/core/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libcore.a: $(libcore_a_OBJECTS) $(libcore_a_DEPENDENCIES) + -rm -f libcore.a + $(libcore_a_AR) libcore.a $(libcore_a_OBJECTS) $(libcore_a_LIBADD) + $(RANLIB) libcore.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libcore_a_OBJECTS) $(libcore_a_LIBADD) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/core/archive.cpp b/src/core/archive.cpp new file mode 100644 index 0000000..0b6a5a7 --- /dev/null +++ b/src/core/archive.cpp @@ -0,0 +1,935 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// archive.cpp -- classes that abstract a raw byte archive +// +// cArchive -- interface for single-direction (one pass) reads and writes +// cBidirArchive -- interface for a random-access archive +// cMemArchive -- implementation of a bidirectional archive in memory +// cFileArchive -- implementation of a bidirectional archive as a file + +#include "stdcore.h" +#include "archive.h" +#include "fsservices.h" + +#include +#include +#include +#include +#include +#include "file.h" +#include "stringutil.h" + +#include "corestrings.h" // for: STR_ERR2_ARCH_CRYPTO_ERR + + + +#if FSEEK_TAKES_INT32 +#define FSEEK(x, y, z) fseek((x), (int32)(y), (z)) +#else +#define FSEEK(x, y, z) fseek((x), (y), (z)) +#endif + + +//============================================================================= +// Utility Functions +//============================================================================= + +/////////////////////////////////////////////////////////////////////////////// +// util_IsDir -- returns true if a given file is a directory +/////////////////////////////////////////////////////////////////////////////// +bool util_IsDir( const TSTRING& fileName ) +{ + cFSStatArgs s; + try + { + iFSServices::GetInstance()->Stat( fileName, s ); + } + catch( eFSServices ) + { + return false; + } + + return( s.mFileType == cFSStatArgs::TY_DIR ); +} + +//============================================================================= +// eArchiveCrypto +//============================================================================= +TSTRING eArchiveCrypto::GetMsg( ) const +{ + // RAD: Updated this to use new stringtable + return ( mMsg + TSS_GetString( cCore, core::STR_ERR2_ARCH_CRYPTO_ERR ) ); +} + + +//============================================================================= +// cArchive +//============================================================================= + +// convenience methods +// +// Specific Read functions throw eArchive if EOF is reached because +// if the caller is requesting a certain amount of data to be present, +// reaching EOF is unexpected +// +// ReadBlob and WriteBlob return number of bytes read or written. Notice +// that ReadBlob does not throw an exception since eventually EOF is expected. +// +// ReadBlob can take NULL as a destination pointer +// +// All write functions throw exceptions for unexpected events like +// running out of memory or disk space. +// + +void cArchive::ReadInt16(int16& ret) // throw(eArchive) +{ + if (ReadBlob(&ret, sizeof(int16)) != sizeof(int16)) + throw eArchiveEOF(); + + ret = tw_ntohs(ret); +} + +void cArchive::ReadInt32(int32& ret) // throw(eArchive) +{ + if (ReadBlob(&ret, sizeof(int32)) != sizeof(int32)) + throw eArchiveEOF(); + + ret = tw_ntohl(ret); +} + +void cArchive::ReadInt64(int64& ret) // throw(eArchive) +{ + if (ReadBlob(&ret, sizeof(int64)) != sizeof(int64)) + throw eArchiveEOF(); + + ret = tw_ntohll(ret); +} + +// NOTE:BAM 10/11/99 -- we store unsigned size, but it really only works with +// lengths < INT16_MAX due to sign extension in integral promotion during the +// resize() in ReadString(). +// format for written string: 16-bit unsigned size, then a list of 16-bit UCS2 (Unicode) characters +// not including terminating NULL +void cArchive::ReadString(TSTRING& ret) // throw(eArchive) +{ + // read in size of string + int16 size; + ReadInt16( size ); + + // create buffer for WCHAR16 string + wc16_string ws; + ws.resize( size ); + WCHAR16* pwc = (WCHAR16*)ws.data(); + + for( int n = 0; n < size; n++ ) + { + int16 i16; + ReadInt16( i16 ); + *pwc++ = i16; + } + + // convert WCHAR16 string to a TSTRING + ret = cStringUtil::WstrToTstr( ws ); +} + +int cArchive::ReadBlob(void* pBlob, int count) +{ + return Read(pBlob, count); +} + +void cArchive::WriteInt16(int16 i) // throw(eArchive) +{ + i = tw_htons(i); + WriteBlob(&i, sizeof(int16)); +} + +void cArchive::WriteInt32(int32 i) // throw(eArchive) +{ + i = tw_htonl(i); + WriteBlob(&i, sizeof(int32)); +} + +void cArchive::WriteInt64(int64 i) // throw(eArchive) +{ + i = tw_htonll(i); + WriteBlob(&i, sizeof(int64)); +} + +// NOTE:BAM 10/11/99 -- we store unsigned size, but it really only works with +// lengths < INT16_MAX due to sign extension in integral promotion during the +// resize() in ReadString(). +// format for written string: 16-bit unsigned size, then a list of 16-bit UCS2 (Unicode) characters +// not including terminating NULL +void cArchive::WriteString(TSTRING s) // throw(eArchive) +{ + // convert string to a UCS2 string + wc16_string ws; + cStringUtil::Convert( ws, s ); // Make convert "type-dispatched" + + // we assume that we can represent the size as a unsigned 16-bit number + // (we actually write it as a signed number, but we cast it) + if( ws.length() > TSS_INT16_MAX ) + ThrowAndAssert( eArchiveStringTooLong() ); + + WriteInt16( static_cast( ws.length() ) ); + + // write out each 16 bit character + // RAD:09/03/99 -- Optimized for performance with "const" + wc16_string::const_iterator at = ws.begin(); + while ( at != ws.end() ) + WriteInt16( *at++ ); +} + + +void cArchive::WriteBlob(const void* pBlob, int count) // throw(eArchive) +{ + if (Write(pBlob, count) < count) + ThrowAndAssert(eArchiveWrite()); +} + +int32 cArchive::GetStorageSize(const TSTRING& str) +{ + int32 size = sizeof(int32); // the length is always stored + // + // after the length, all of the characters in the string are written as 16-bit values, + // except for the null character + // + size += ( str.length() * 2 ); + + return size; +} + +int64 cArchive::Copy(cArchive* pFrom, int64 amt) +{ + enum { BUF_SIZE = 2048 }; + int8 buf[BUF_SIZE]; + int64 amtLeft = amt; + + while(amtLeft > 0) + { + int64 amtToRead = amtLeft > BUF_SIZE ? BUF_SIZE : amtLeft; + int64 amtRead = pFrom->ReadBlob(buf, static_cast( amtToRead ) ); + amtLeft -= amtRead; + WriteBlob(buf, static_cast( amtRead ) ); + if(amtRead < amtToRead) + break; + } + + // return the amount copied ... + return (amt - amtLeft); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cMemMappedArchive -- Archive that can be memory mapped. +/////////////////////////////////////////////////////////////////////////////// + +cMemMappedArchive::cMemMappedArchive() +{ + mpMappedMem = 0; + mMappedOffset = 0; + mMappedLength = 0; +} + +cMemMappedArchive::~cMemMappedArchive() +{ +} + +int64 cMemMappedArchive::GetMappedOffset() const // throw(eArchive) +{ + if (mpMappedMem == 0) + ThrowAndAssert(eArchiveMemmap()); + + return mMappedOffset; +} + +int64 cMemMappedArchive::GetMappedLength() const // throw(eArchive) +{ + if (mpMappedMem == 0) + ThrowAndAssert(eArchiveMemmap()); + + return mMappedLength; +} + +const void* cMemMappedArchive::GetMap() const // throw(eArchive) +{ + if (mpMappedMem == 0) + ThrowAndAssert(eArchiveMemmap()); + + return mpMappedMem; +} + +void* cMemMappedArchive::GetMap() // throw(eArchive) +{ + if (mpMappedMem == 0) + ThrowAndAssert(eArchiveMemmap()); + + return mpMappedMem; +} + +void cMemMappedArchive::SetNewMap(void* pMap, int64 offset, int64 length) const +{ + if (pMap == 0) + { + mpMappedMem = 0; + mMappedOffset = 0; + mMappedLength = 0; + } + else + { + mpMappedMem = pMap; + mMappedOffset = offset; + mMappedLength = length; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// class cMemoryArchive -- An archive that stores itself in a memory buffer. +// This buffer can grow as needed up until a pre-specified maximum +// size. The buffer can be read and written to and can be memory +// mapped. +/////////////////////////////////////////////////////////////////////////////// + +cMemoryArchive::cMemoryArchive(int maxSize) +: mMaxAllocatedLen(maxSize) +{ + ASSERT(maxSize > 0); + mpMemory = 0; + mAllocatedLen = 0; + mLogicalSize = 0; + mReadHead = 0; +} + +cMemoryArchive::~cMemoryArchive() +{ + delete [] mpMemory; +} + +bool cMemoryArchive::EndOfFile() +{ + return mReadHead >= mLogicalSize; +} + +void cMemoryArchive::Seek(int64 offset, SeekFrom from) // throw(eArchive) +{ + switch (from) + { + case cBidirArchive::BEGINNING: + break; + case cBidirArchive::CURRENT: + offset = mReadHead + (int)offset; + break; + case cBidirArchive::END: + offset = mLogicalSize + (int)offset; + break; + default: + ThrowAndAssert(eArchiveSeek(TSS_GetString( cCore, core::STR_MEMARCHIVE_FILENAME), TSS_GetString( cCore, core::STR_MEMARCHIVE_ERRSTR))); + } + + if (offset > mLogicalSize) + ThrowAndAssert(eArchiveSeek(TSS_GetString( cCore, core::STR_MEMARCHIVE_FILENAME), TSS_GetString( cCore, core::STR_MEMARCHIVE_ERRSTR))); + + mReadHead = static_cast( offset ); +} + +int64 cMemoryArchive::CurrentPos() const +{ + return mReadHead; +} + +int64 cMemoryArchive::Length() const +{ + return mLogicalSize; +} + +void cMemoryArchive::Truncate() +{ + ASSERT(mReadHead >= 0); + + mLogicalSize = mReadHead; + AllocateMemory(mLogicalSize); +} + +void cMemoryArchive::MapArchive(int64 offset, int64 len) // throw(eArchive) +{ + if ( offset + (int)len > mLogicalSize ) + AllocateMemory( static_cast( offset + len ) ); + + SetNewMap(mpMemory + offset, offset, len); +} + +void cMemoryArchive::MapArchive(int64 offset, int64 len) const // throw(eArchive) +{ + if (offset + (int)len > mLogicalSize) + ThrowAndAssert(eArchiveMemmap()); + + SetNewMap(mpMemory + offset, offset, len); +} + +int cMemoryArchive::Read(void* pDest, int count) +{ + if (mReadHead + count > mLogicalSize) + count = mLogicalSize - mReadHead; + + if (pDest != 0) + memcpy(pDest, mpMemory + mReadHead, count); + + mReadHead += count; + + return count; +} + +int cMemoryArchive::Write(const void* pDest, int count) // throw(eArchive) +{ + if (mReadHead + count > mLogicalSize) + { + AllocateMemory(mReadHead + count); + } + + memcpy(mpMemory + mReadHead, pDest, count); + + mReadHead += count; + + return count; +} + +void cMemoryArchive::AllocateMemory(int len) // throw(eArchive) +{ + const int MIN_ALLOCATED_SIZE = 1024; + + if (len > mAllocatedLen) + { + // grow the buffer + // only error if we are in debug mode +#ifdef _DEBUG + if (len > mMaxAllocatedLen) + ThrowAndAssert(eArchiveOutOfMem()); +#endif + + if( 0 == mAllocatedLen ) + mAllocatedLen = MIN_ALLOCATED_SIZE; + + while (mAllocatedLen < len) + mAllocatedLen *= 2; + + int8* pNewMem = new int8[mAllocatedLen]; + if (mpMemory != 0) + { + memcpy(pNewMem, mpMemory, mLogicalSize); + delete [] mpMemory; + } + mpMemory = pNewMem; + mLogicalSize = len; + + // update memory map if there is one + if (mpMappedMem) + SetNewMap(mpMemory + mMappedOffset, mMappedOffset, mMappedLength); + } + else + { + // check for memory map conflict + if (mpMappedMem && len < mMappedOffset + mMappedLength) + ThrowAndAssert(eArchiveMemmap()); + + if (len < (mAllocatedLen >> 1) && mAllocatedLen > MIN_ALLOCATED_SIZE) + { + // shrink the buffer + int8* pNewMem = new int8[len]; + ASSERT(mpMemory); + memcpy(pNewMem, mpMemory, len); + delete [] mpMemory; + mpMemory = pNewMem; + mLogicalSize = len; + + // update memory map if there is one + if (mpMappedMem) + SetNewMap(mpMemory + mMappedOffset, mMappedOffset, mMappedLength); + } + else + { + // no need to grow or shrink + mLogicalSize = len; + } + } +} +/* +class cFixedMemArchive : public cBidirArchive +{ +public: + + int8* mpMemory; + int32 mSize; + int32 mReadHead; +}; +*/ + +//----------------------------------------------------------------------------- +// cFixedMemArchive +//----------------------------------------------------------------------------- +cFixedMemArchive::cFixedMemArchive() +: mpMemory (0), + mSize (0), + mReadHead (0) +{ +} + +cFixedMemArchive::cFixedMemArchive( int8* pMem, int32 size ) +: mpMemory (0), + mSize (0), + mReadHead (0) +{ + Attach( pMem, size ); +} + +cFixedMemArchive::~cFixedMemArchive() +{ +} + +void cFixedMemArchive::Attach( int8* pMem, int32 size ) +{ + mpMemory = pMem; + mSize = size; + mReadHead = 0; +} + +void cFixedMemArchive::Seek(int64 offset, SeekFrom from) // throw(eArchive) +{ + switch (from) + { + case cBidirArchive::BEGINNING: + break; + case cBidirArchive::CURRENT: + offset = mReadHead + (int)offset; + break; + case cBidirArchive::END: + offset = mSize + (int)offset; + break; + default: + ThrowAndAssert(eArchiveSeek(TSS_GetString( cCore, core::STR_MEMARCHIVE_FILENAME), TSS_GetString( cCore, core::STR_MEMARCHIVE_ERRSTR))); + } + + if (offset > mSize) + ThrowAndAssert(eArchiveSeek(TSS_GetString( cCore, core::STR_MEMARCHIVE_FILENAME), TSS_GetString( cCore, core::STR_MEMARCHIVE_ERRSTR))); + + mReadHead = static_cast( offset ); +} + +int64 cFixedMemArchive::CurrentPos() const +{ + return mReadHead; +} + +int64 cFixedMemArchive::Length() const +{ + return mSize; +} + +bool cFixedMemArchive::EndOfFile() +{ + return (mReadHead >= mSize); +} + +int cFixedMemArchive::Read(void* pDest, int count) // throw(eArchive) +{ + ASSERT( pDest ); + if (mReadHead + count > mSize) + { + count = static_cast( mSize - mReadHead ); + if (count <= 0) + return 0; + } + + if (pDest != 0) + memcpy(pDest, mpMemory + mReadHead, count); + + mReadHead += count; + + return count; +} + +int cFixedMemArchive::Write(const void* pDest, int count) // throw(eArchive) +{ + if (mReadHead + count > mSize) + { + ASSERT( false ); + throw eArchiveWrite(); + } + + memcpy(mpMemory + mReadHead, pDest, count); + + mReadHead += count; + + return count; +} + + +/////////////////////////////////////////////////////////////////////////////// +// class cFileArchive -- Archive for files... +/////////////////////////////////////////////////////////////////////////////// + +//Ctor -- Initialize member variables to 0 or NULL equivalents. +cFileArchive::cFileArchive() : + mFileSize(0), + mReadHead(0), + isWritable(false) +{} + +cFileArchive::~cFileArchive() +{ +} + +bool cFileArchive::EndOfFile() +{ + return ( mReadHead >= mFileSize ); +} + +//////////////////////////////////////////////////////////////////////// +// Seek -- This is where the actual offset is performed. The default +// for each archive will be 0. +///////////////////////////////////////////////////////////////////////// +void cFileArchive::Seek( int64 offset, SeekFrom from) // throw(eArchive) +{ + try + { + switch (from) + { + case cBidirArchive::BEGINNING: + break; + case cBidirArchive::CURRENT: + offset = mReadHead + offset; + break; + case cBidirArchive::END: + offset = mFileSize + offset; + break; + default: + throw eArchiveSeek( mCurrentFilename, iFSServices::GetInstance()->GetErrString() ) ; + } + + if ( offset > mFileSize ) + throw eArchiveSeek( mCurrentFilename, iFSServices::GetInstance()->GetErrString() ) ; + mReadHead = offset; + + mCurrentFile.Seek(mReadHead, cFile::SEEK_BEGIN); + //This is where the actual read/writehead is set!! + }//try + catch( eFile& fileError ) + { + throw( eArchiveSeek( mCurrentFilename, fileError.GetDescription() ) ); + } +} + +int64 cFileArchive::CurrentPos(void) const +{ + return mReadHead; +} + +///////////////////////////////////////////////////////////////////////// +// Length -- Returns the size of the current file archive. +///////////////////////////////////////////////////////////////////////// +int64 cFileArchive::Length(void) const +{ + try + { + return mCurrentFile.GetSize(); + } + catch(eFile& fileError) + { + throw( eArchiveSeek( mCurrentFilename, fileError.GetDescription() ) ); + } +} + +///////////////////////////////////////////////////////////////////////// +// OpenRead -- Opens the file to be read only. +///////////////////////////////////////////////////////////////////////// +void cFileArchive::OpenRead(const TCHAR* filename, uint32 openFlags) +{ + try + { + // set up open flags + uint32 flags = cFile::OPEN_READ; + flags |= ( ( openFlags & FA_OPEN_TRUNCATE ) ? cFile::OPEN_TRUNCATE : 0 ); + flags |= ( ( openFlags & FA_OPEN_TEXT ) ? cFile::OPEN_TEXT : 0 ); + + mCurrentFilename = filename; + mCurrentFile.Open( filename, flags ); + isWritable = false; + + mFileSize = mCurrentFile.GetSize(); + mReadHead = mCurrentFile.Seek( 0, cFile::SEEK_BEGIN ); + } + catch(eFile& fileError) + { + throw(eArchiveOpen( mCurrentFilename, fileError.GetDescription() ) ); + } +} + +///////////////////////////////////////////////////////////////////////// +// OpenReadWrite -- Opens the file to be read or written to +///////////////////////////////////////////////////////////////////////// +void cFileArchive::OpenReadWrite(const TCHAR* filename, uint32 openFlags) +{ + try + { + // set up open flags + uint32 flags = cFile::OPEN_WRITE; + flags |= ( ( openFlags & FA_OPEN_TRUNCATE ) ? cFile::OPEN_TRUNCATE : 0 ); + flags |= ( ( openFlags & FA_OPEN_TEXT ) ? cFile::OPEN_TEXT : 0 ); + + mCurrentFilename = filename; + mCurrentFile.Open( filename, flags ); + isWritable = true; + + mFileSize = mCurrentFile.GetSize(); + mReadHead = mCurrentFile.Seek( 0, cFile::SEEK_BEGIN ); + } + catch(eFile& fileError) + { + throw( eArchiveOpen( mCurrentFilename, fileError.GetDescription() ) ); + } +} + +///////////////////////////////////////////////////////////////////////// +// GetCurrentFilename -- Returns the name of the file currently associated +// with the FileArchive. +///////////////////////////////////////////////////////////////////////// +TSTRING cFileArchive::GetCurrentFilename(void) const +{ + return mCurrentFilename; +} + +///////////////////////////////////////////////////////////////////////// +// Close -- Closes the file currently referenced by mpCurrStream +///////////////////////////////////////////////////////////////////////// +void cFileArchive::Close() +{ + try + { + mCurrentFile.Close(); + mFileSize = 0; + mReadHead = 0; + + mCurrentFilename = _T(""); + } + catch(eFile& fileError) + { + throw( eArchive( mCurrentFilename, fileError.GetDescription() ) ); + } +} + +///////////////////////////////////////////////////////////////////////// +// Read -- Read places bytes in location designated by pDest. Returns +// The actual amount read into *pDest. +///////////////////////////////////////////////////////////////////////// +int cFileArchive::Read(void* pDest, int count) +{ + try + { + if ( mReadHead + count > mFileSize ) + count = static_cast( mFileSize - mReadHead ); + + if ( pDest != NULL ) + { + int nbRead = + static_cast( mCurrentFile.Read( pDest, count ) ); + + // 'count' may not be equal to 'nbRead' if the file is open in + // text mode. + count = nbRead; + if(count < 0) count = 0; + } + else + { + int i; + int32 dummy; + for (i = count; ; i -= sizeof(int32)) + { + if (i < (int)sizeof(int32)) + { + if (i > 0) + mCurrentFile.Read( &dummy, i ); + break; + } + mCurrentFile.Read( &dummy, i ); + } + } + + mReadHead += count; + return count; + } + catch( eFile& fileError ) + { + throw( eArchiveRead( mCurrentFilename, fileError.GetDescription() ) ); + } + +} + +///////////////////////////////////////////////////////////////////////// +// Write -- Writes to file designated by fh. If isWritable is not set, +// function returns 0. Otherwise, the actual # written is returned. +///////////////////////////////////////////////////////////////////////// +int cFileArchive::Write(const void* pDest, int count) // throw(eArchive) +{ + try + { + int64 actual_count = 0; + ASSERT( mCurrentFile.isWritable ); + + actual_count = mCurrentFile.Write( pDest, count ); + + if ( actual_count < count ) + { + //Disk full?? + throw eArchiveWrite( mCurrentFilename, iFSServices::GetInstance()->GetErrString() ) ; + } + + // increment the read/write head + mReadHead += actual_count; + + // increase the size, if needed + if( mReadHead > mFileSize ) + { + #if 0 // IS_SUNPRO + // These two lines seem to be all there is between code that crashes and code that works for sunpro + cDebug d("cFileArchive::Write()"); + d.TraceDebug(_T("file(%s) adjusted mFileSize = %d mReadHead = %d\n"), mCurrentFilename.c_str(), (int)mFileSize, (int)mReadHead); + #endif + mFileSize = mReadHead; + } + + return (int)actual_count; + } + catch( eFile& fileError ) + { + throw( eArchiveWrite( mCurrentFilename, fileError.GetDescription() ) ); + } +} + + +///////////////////////////////////////////////////////////////////////// +// Truncate +///////////////////////////////////////////////////////////////////////// +void cFileArchive::Truncate() // throw(eArchive) +{ + ASSERT( mCurrentFile.IsOpen() ); + ASSERT( mCurrentFile.isWritable ); + + try + { + mCurrentFile.Truncate ( mReadHead ); + } + catch( eFile& fileError ) + { + //TODO: create an error number for truncate... + throw( eArchiveWrite( mCurrentFilename, fileError.GetDescription() ) ); + } + + mFileSize = mReadHead; +} + + + +///////////////////////////////////////////////////////////////////////// +// OpenReadWrite -- Opens the file to be read or written to +// +// since we'll never open an existing file, the truncateFile flag is unnecessary. +///////////////////////////////////////////////////////////////////////// +void cLockedTemporaryFileArchive::OpenReadWrite( const TCHAR* filename, uint32 openFlags ) +{ + TSTRING strTempFile; + + try { + + ASSERT( !mCurrentFile.IsOpen() ); // shouldn't be able to create a new file when we're already open + if ( mCurrentFile.IsOpen() ) + throw( eArchive( mCurrentFilename, _T("Internal Error") ) ); + + + /////////////////////////////////////////////////////////////////////////////// + // if filename is NULL, create a temp file for the caller + if( filename == NULL ) + { + try + { + iFSServices::GetInstance()->GetTempDirName( strTempFile ); + strTempFile += _T("twtempXXXXXX"); + iFSServices::GetInstance()->MakeTempFilename( strTempFile ); + } + catch( eFSServices& e) + { + TSTRING errStr = TSS_GetString( cCore, core::STR_BAD_TEMPDIRECTORY ); + eArchiveOpen e(strTempFile, errStr); + throw e; + } + } + /////////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////////// + // create file + + // set up flags + uint32 flags = cFile::OPEN_WRITE | cFile::OPEN_LOCKED_TEMP | cFile::OPEN_CREATE | cFile::OPEN_EXCLUSIVE; + if ( openFlags & FA_OPEN_TRUNCATE ) + flags |= cFile::OPEN_TRUNCATE; + if ( openFlags & FA_OPEN_TEXT ) + flags |= cFile::OPEN_TEXT; + + // open file + mCurrentFilename = filename ? filename : strTempFile.c_str(); + mCurrentFile.Open( mCurrentFilename, flags ); + + isWritable = true; + mFileSize = mCurrentFile.GetSize(); + mReadHead = mCurrentFile.Seek( 0, cFile::SEEK_BEGIN ); + +#if 0 // IS_SUNPRO + cDebug d("cLockedTemporaryFileArchive::OpenReadWrite()"); + d.TraceDebug(_T("file(%s) set mFileSize to %d mReadHead to %d\n"), mCurrentFilename.c_str(), (int)mFileSize, (int)mReadHead); +#endif + + }//try + catch (eFile& fileError) { + TSTRING errStr = TSS_GetString( cCore, core::STR_BAD_TEMPDIRECTORY ); + eArchiveOpen e(strTempFile, errStr); + throw e; + } + + /////////////////////////////////////////////////////////////////////////////// +} + +///////////////////////////////////////////////////////////////////////// +// Close -- Closes the file currently referenced by fh +void cLockedTemporaryFileArchive::Close() +{ + // Note: this deletes the file as well + cFileArchive::Close(); +} + diff --git a/src/core/archive.h b/src/core/archive.h new file mode 100644 index 0000000..8aafe04 --- /dev/null +++ b/src/core/archive.h @@ -0,0 +1,346 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// archive.h -- classes that abstract a raw byte archive +// +// cArchive -- interface for single-direction (one pass) reads and writes +// cBidirArchive -- interface for a random-access archive +// cMemArchive -- implementation of a bidirectional archive in memory +// cFileArchive -- implementation of a bidirectional archive as a file + +#ifndef __ARCHIVE_H +#define __ARCHIVE_H + +#ifndef __DEBUG_H +#include "debug.h" +#endif +#ifndef __ERRORUTIL_H +#include "errorutil.h" +#endif +#ifndef __FILEERROR_H +#include "fileerror.h" +#endif +#ifndef __FILE_H +#include "file.h" +#endif + +//============================================================================= +// eArchive exception classes +//============================================================================= +TSS_FILE_EXCEPTION( eArchive, eFileError ); +TSS_FILE_EXCEPTION( eArchiveOpen, eArchive ); +TSS_FILE_EXCEPTION( eArchiveWrite, eArchive ); +TSS_FILE_EXCEPTION( eArchiveRead, eArchive ); +TSS_FILE_EXCEPTION( eArchiveEOF, eArchive ); +TSS_FILE_EXCEPTION( eArchiveSeek, eArchive ); +TSS_FILE_EXCEPTION( eArchiveMemmap, eArchive ); +TSS_FILE_EXCEPTION( eArchiveOutOfMem, eArchive ); +TSS_FILE_EXCEPTION( eArchiveInvalidOp, eArchive ); +TSS_FILE_EXCEPTION( eArchiveFormat, eArchive ); +TSS_FILE_EXCEPTION( eArchiveNotRegularFile, eArchive ); +TSS_BEGIN_EXCEPTION( eArchiveCrypto, eArchive ) + + virtual TSTRING GetMsg() const; + // eCryptoArchive appends a special string to the end of + // all exception messages +TSS_END_EXCEPTION() +TSS_EXCEPTION( eArchiveStringTooLong, eArchive ); + +// throw( eArchiveOpen( cErrorUtil::MakeFileError( fileError.GetMsg(), strTempFile ) ) ); + + +//============================================================================= +// cArchive +//============================================================================= + +class cArchive +{ +public: + // convenience methods + // + // Specific Read functions throw(eArchive) if EOF is reached because + // if the caller is requesting a certain amount of data to be present, + // reaching EOF is unexpected + // + // ReadBlob and WriteBlob return number of bytes read or written. Notice + // that ReadBlob does not throw an exception since eventually EOF is expected. + // + // ReadBlob can take NULL as a destination pointer + // + // All write functions throw exceptions for unexpected events like + // running out of memory or disk space. + // + void ReadInt16(int16& ret); // throw(eArchive) + void ReadInt32(int32& ret); // throw(eArchive) + void ReadInt64(int64& ret); // throw(eArchive) + void ReadString(TSTRING& ret); // throw(eArchive) + int ReadBlob(void* pBlob, int count); + void WriteInt16(int16 i); // throw(eArchive) + void WriteInt32(int32 i); // throw(eArchive) + void WriteInt64(int64 i); // throw(eArchive) + void WriteString(TSTRING s); // throw(eArchive) + void WriteBlob(const void* pBlob, int count); // throw(eArchive) + + static int32 GetStorageSize(const TSTRING& str); + // this method calculates how many bytes the given string will take up in the archive and returns + // that value + // NOTE -- if the implementation of ReadString() or WriteString() ever changes, this method will also + // need to change. + + int64 Copy(cArchive* pFrom, int64 amt); // throw(eArchive) + // this method copies amt bytes from pFrom to itself, throwing an eArchive if anything goes wrong. + + // only makes sense to call for reading archives + virtual bool EndOfFile() = 0; + +protected: + // overrides + virtual int Read(void* pDest, int count) = 0; + virtual int Write(const void* pDest, int count) = 0; // throw(eArchive); +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cBidirArchive -- +/////////////////////////////////////////////////////////////////////////////// + +class cBidirArchive : public cArchive +{ +public: + enum SeekFrom { + BEGINNING = 0, + CURRENT = 1, + END = -1 + }; + + virtual void Seek(int64 offset, SeekFrom from) = 0; // throw(eArchive); + virtual int64 CurrentPos() const = 0; + virtual int64 Length() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cMemMappedArchive -- Archive that can be memory mapped. +/////////////////////////////////////////////////////////////////////////////// + +class cMemMappedArchive : public cBidirArchive +{ +public: + enum { + MAP_TO_EOF = -1 + }; + + cMemMappedArchive(); + virtual ~cMemMappedArchive(); + + virtual void MapArchive(int64 offset, int64 len) = 0; // throw(eArchive); + virtual void MapArchive(int64 offset, int64 len) const = 0; // throw(eArchive); + // the const version of MapArchive() does not allow the archive to grow in size + + int64 GetMappedOffset() const; // throw(eArchive) + int64 GetMappedLength() const; // throw(eArchive) + void* GetMap(); // throw(eArchive) + const void* GetMap() const; + +protected: + mutable void* mpMappedMem; + mutable int64 mMappedOffset; + mutable int64 mMappedLength; + + // call in derived class to set above vars + void SetNewMap(void* pMap, int64 offset, int64 length) const; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cMemoryArchive -- An archive that stores itself in a memory buffer. +// This buffer can grow as needed up until a pre-specified maximum +// size. The buffer can be read and written to and can be memory +// mapped. +/////////////////////////////////////////////////////////////////////////////// + +class cMemoryArchive : public cMemMappedArchive +{ +public: + cMemoryArchive(int maxSize = 0x8000000); // default max size == 128MB + ~cMemoryArchive(); + + virtual bool EndOfFile(); + virtual void Seek(int64 offset, SeekFrom from); // throw(eArchive) + virtual int64 CurrentPos() const; + virtual int64 Length() const; + virtual void MapArchive(int64 offset, int64 len); // throw(eArchive) + virtual void MapArchive(int64 offset, int64 len) const; // throw(eArchive) + + void Truncate(); // set the length to the current pos + + int8* GetMemory() const { return mpMemory; } + +protected: + int8* mpMemory; + int mAllocatedLen; + int mMaxAllocatedLen; + int mLogicalSize; + int mReadHead; + + virtual int Read(void* pDest, int count); + virtual int Write(const void* pDest, int count); // throw(eArchive) + virtual void AllocateMemory(int len); // throw(eArchive) +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFixedMemArchive -- a memory archive that operates on a fixed-sized block of +// memory that has already been allocated +/////////////////////////////////////////////////////////////////////////////// +class cFixedMemArchive : public cBidirArchive +{ +public: + cFixedMemArchive(); + cFixedMemArchive( int8* pMem, int32 size ); + virtual ~cFixedMemArchive(); + + void Attach( int8* pMem, int32 size ); + // this method associates the archive with pMem and sets the size of the + // archive. Unlike cMemoryArchive, this may never grow or shrink in size. + + //----------------------------------- + // cBidirArchive interface + //----------------------------------- + virtual void Seek (int64 offset, SeekFrom from) ; // throw(eArchive); + virtual int64 CurrentPos () const ; + virtual int64 Length () const ; + virtual bool EndOfFile(); +protected: + //----------------------------------- + // cArchive interface + //----------------------------------- + virtual int Read(void* pDest, int count); // throw(eArchive) + virtual int Write(const void* pDest, int count); // throw(eArchive) + + int8* mpMemory; + int32 mSize; + int32 mReadHead; +}; + +class cFileArchive : public cBidirArchive +{ +public: + cFileArchive(); + virtual ~cFileArchive(); + + enum OpenFlags + { + FA_OPEN_TEXT = 0x1, + FA_OPEN_TRUNCATE = 0x2 + }; + + // TODO: Open should throw + virtual void OpenRead(const TCHAR* filename, uint32 openFlags = 0 ); + virtual void OpenReadWrite(const TCHAR* filename, uint32 openFlags = FA_OPEN_TRUNCATE ); + // opens a file for reading or writing; the file is always created if it doesn't exist, + // and is truncated to zero length if truncateFile is set to true; + TSTRING GetCurrentFilename(void) const; + virtual void Close(void); + void Truncate(); // throw(eArchive) // set the length to the current pos + + //----------------------------------- + // cBidirArchive interface + //----------------------------------- + virtual bool EndOfFile(); + virtual void Seek(int64 offset, SeekFrom from); // throw(eArchive) + virtual int64 CurrentPos() const; + virtual int64 Length() const; + + +protected: + int64 mFileSize; //Size of FileArchive + int64 mReadHead; //Current position of read/write head + //----------------------------------- + // cArchive interface + //----------------------------------- + virtual int Read(void* pDest, int count); + virtual int Write(const void* pDest, int count); //throw(eArchive) + bool isWritable; + cFile mCurrentFile; + TSTRING mCurrentFilename; //current file +}; + +/////////////////////////////////////////////////////////////// +// cLockedTemporaryFileArchive -- this class uses as an archive a file +// that is not accessable to any other process besides the calling one. +// the file will be deleted from the filesystem on Close(); +// +// implemented by using cFileArchive and overwriting open and close +// functions +// +class cLockedTemporaryFileArchive : public cFileArchive +{ +public: + virtual void OpenReadWrite ( const TCHAR* filename = NULL, uint32 openFlags = FA_OPEN_TRUNCATE ); + // creates the file. filename must not exist on the file system. + // if filename is NULL, the class will create and use a temporary file. + // truncateFile has no meaning + //virtual void OpenReadWriteThrow ( const TCHAR* filename = NULL, bool truncateFile = true ) throw (eArchive); + // this is the same as OpenReadWrite, except an exception is thrown on error (of type + // cArchive::ERR_OPEN_FAILED) + + virtual void Close(); + // close and delete the file +private: + // open for read only makes no sense if we're always creating the file, + // so disallow read only file opens + virtual void OpenRead( const TCHAR*, uint32 openFlags = 0 ) { ASSERT( false ); THROW_INTERNAL("archive.h"); } +}; + + + +/* +// TODO: fill these out + +/////////////////////////////////////////////////////////////////////////////// +// class cMMFileArchive -- +/////////////////////////////////////////////////////////////////////////////// + +class cMMFileArchive : public cMemMappedArchive +{ +public: +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cNetArchive -- +/////////////////////////////////////////////////////////////////////////////// + +class cNetArchive : public cArchive +{ +public: +}; +*/ + +#endif + diff --git a/src/core/archive_t.cpp b/src/core/archive_t.cpp new file mode 100644 index 0000000..ed72285 --- /dev/null +++ b/src/core/archive_t.cpp @@ -0,0 +1,188 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// archive_t.cpp +// +// test the archive component + +#include "stdcore.h" +#include "archive.h" +#include "test/test.h" +#include "error.h" +#include + +TSS_EXCEPTION(eTestArchiveError, eError); + +void TestArchive() +{ + // cMemoryArchive + cMemoryArchive memarch; + + memarch.WriteInt32(1); + memarch.WriteInt32(2); + memarch.WriteInt32(3); + memarch.WriteInt32(4); + + TSTRING s = _T("Weenus"); + memarch.WriteString(s); + + memarch.WriteInt64(1234567L); + + memarch.WriteInt16(42); + + memarch.Seek(0, cBidirArchive::BEGINNING); + + int32 i; + int64 l; + memarch.ReadInt32(i); + TEST(i == 1); + memarch.ReadInt32(i); + TEST(i == 2); + memarch.ReadInt32(i); + TEST(i == 3); + memarch.ReadInt32(i); + TEST(i == 4); + + TSTRING s2; + memarch.ReadString(s2); + TEST(s2.compare(_T("Weenus")) == 0); + + memarch.ReadInt64(l); + TEST(l == 1234567L); + + TEST(memarch.ReadBlob(NULL, sizeof(int16)) == sizeof(int16)); + TEST(memarch.ReadBlob(NULL, 1024) == 0); + + try { + memarch.ReadInt32(i); + throw eTestArchiveError(); + } + catch (eArchive& e) + { + // Cool we got the right exception + (void)e; + } + catch (eError& e) + { + TEST(false); + (void)e; + } + + memarch.MapArchive(4 * sizeof(int32) + sizeof(int32) + 6, sizeof(int64)); + TEST(memarch.GetMappedOffset() == 4 * sizeof(int32) + sizeof(int32) + 6); + TEST(memarch.GetMappedLength() == sizeof(int64)); +// TEST(tw_ntohll(*(int64*)memarch.GetMap()) == 1234567L); + + + // cLockedTemporaryFileArchive + TSTRING lockedFileName = TEMP_DIR; + lockedFileName += _T("/inaccessable_file.bin"); + + cLockedTemporaryFileArchive lockedArch; + + // try to create an archive using a temp file + lockedArch.OpenReadWrite(); + lockedArch.Close(); + + // this should open and lock the file -- shouldn't be able to access it + lockedArch.OpenReadWrite(lockedFileName.c_str()); + lockedArch.Seek(0, cBidirArchive::BEGINNING); + + // shouldn't be able to see these changes + lockedArch.WriteInt32(1); + lockedArch.WriteInt32(2); + lockedArch.WriteInt32(3); + lockedArch.WriteInt32(4); + lockedArch.WriteString(s); + lockedArch.WriteInt64(1234567L); + lockedArch.WriteInt16(42); + + // this should delete the file + lockedArch.Close(); + + // cFileArchive + TSTRING fileName = TEMP_DIR; + fileName += _T("/archive_test.bin"); + + cFileArchive filearch; + filearch.OpenReadWrite(fileName.c_str()); + filearch.Seek(0, cBidirArchive::BEGINNING); + + filearch.WriteInt32(1); + filearch.WriteInt32(2); + filearch.WriteInt32(3); + filearch.WriteInt32(4); + + filearch.WriteString(s); + filearch.WriteInt64(1234567L); + + filearch.WriteInt16(42); + filearch.Close(); + + int32 j; + int64 k; + filearch.OpenRead(fileName.c_str()); + filearch.Seek(0, cBidirArchive::BEGINNING); + filearch.ReadInt32(j); + TEST(j == 1); + filearch.ReadInt32(j); + TEST(j == 2); + filearch.ReadInt32(j); + TEST(j == 3); + filearch.ReadInt32(j); + TEST(j == 4); + + TSTRING s3; + filearch.ReadString(s3); + TEST(s3.compare(_T("Weenus")) == 0); + filearch.ReadInt64(k); + TEST(k == 1234567L); + + TEST(filearch.ReadBlob(NULL, sizeof(int16)) == sizeof(int16)); + TEST(filearch.ReadBlob(NULL, 1024) == 0); // should be EOF + + try { + filearch.ReadInt32(j); + throw eTestArchiveError(); + } + catch (eArchive& e) + { + // Cool we got the right exception + (void)e; + } + catch (eError& e) + { + TEST(false); + (void)e; + } +} + diff --git a/src/core/charutil.cpp b/src/core/charutil.cpp new file mode 100644 index 0000000..6437d08 --- /dev/null +++ b/src/core/charutil.cpp @@ -0,0 +1,190 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: charutil.cpp +// Date....: 10/20/99 +// Creator.: Brian McFeely (bmcfeely) +// +// [Description] +// + +#include "stdcore.h" +#include "charutil.h" +#include "ntmbs.h" + +/* NOW WE USE tss::strinc +// like mblen but also for wchar_t +int util_tlen( const TCHAR* cur, size_t count ) +{ + int nch = -2; // 'unused' value + + ASSERT( count >= 0 ); + #ifdef _UNICODE + if( count > 0 ) + nch = 1; // next char is always one TCHAR long + else + nch = 0; // no more chars + #else + nch = ::mblen( cur, count ); // here sizeof(TCHAR) == 1 + #endif + + ASSERT( nch != -2 ); // make sure nch was set + return nch; +} +*/ + + +// +// finds the next whole character in string identified by ['cur'-'end') +// identifies beginning of char in 'first', then end of character in 'last' +// returns number of TCHARs that make up the next character +// if there are no more characters, will return 0 and first = last = end +// POSTCONDITIONS: +// +// RETURNS: +// +// THROWS: +// +// COMPLEXITY: +// +// + +/* static */ +bool cCharUtil::PeekNextChar( const TSTRING::const_iterator& cur, + const TSTRING::const_iterator& end, + TSTRING::const_iterator& first, + TSTRING::const_iterator& last ) +{ + // + // do we have a valid string here? + // + if( cur > end ) + { + return false; + } + + if( cur == end ) + { + first = last = end; + return false; + } + + if( *cur == _T('\0') ) + { + first = last = cur; + return false; + } + + first = cur; +// last = tss::strinc( cur ); + last = *cur ? cur + 1 : cur; + return true; +} + + +/* OLD way of doing this... + NOW WE USE tss::strinc +int cCharUtil::PeekNextChar( const TSTRING::const_iterator& cur, + const TSTRING::const_iterator& end, + TSTRING::const_iterator& first, + TSTRING::const_iterator& last, + bool fThrowOnError ) +{ + // + // do we have a valid string here? + // + if( cur > end ) + return -1; + + // + // determine length of character in TCHARs + // + int charSizeInTCHARs = util_tlen( cur, (size_t)end - (size_t)cur ); + if( charSizeInTCHARs == -1 ) // TODO:BAM -- what if size is zero? does that make sense? + { + if( fThrowOnError ) + throw eCharUtilUnrecognizedChar(); + else + return -1; + } + + // + // denote beginning and end of character + // + first = cur; // first char always starts at 'cur' + last = first + charSizeInTCHARs; + + // + // there exist more characters + // + return charSizeInTCHARs; +} +*/ + +//============================================================================= +// +// /* static */ +// bool cCharUtil::PopNextChar( TSTRING::const_iterator& cur, +// const TSTRING::const_iterator& end, +// TSTRING::const_iterator& first, +// TSTRING::const_iterator& last ) +//----------------------------------------------------------------------------- +// REQUIRES: +// +// EFFECTS: +// +// same as PeekNextChar but increments 'cur' to 'last' +// +// POSTCONDITIONS: +// +// RETURNS: +// +// THROWS: +// +// COMPLEXITY: +// +// + +/* static */ +bool cCharUtil::PopNextChar( TSTRING::const_iterator& cur, + const TSTRING::const_iterator& end, + TSTRING::const_iterator& first, + TSTRING::const_iterator& last ) +{ + bool f = PeekNextChar( cur, end, first, last ); + + cur = last; // pop causes 'cur' to move to just beyond character ('last') + + return f; +} + +// eof: charutil.cpp diff --git a/src/core/charutil.h b/src/core/charutil.h new file mode 100644 index 0000000..6d0c2ff --- /dev/null +++ b/src/core/charutil.h @@ -0,0 +1,66 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: charutil.h +// Date....: 10/20/99 +// Creator.: Brian McFeely (bmcfeely) +// +// [Description] +// + +#ifndef __CHARUTIL_H +#define __CHARUTIL_H + +// TODO:BAM -- get rid of this class and just use tss::strinc() !!!!! +class cCharUtil +{ +public: + + + // finds the next whole character in string identified by ['cur'-'end') + // identifies beginning of char in 'first', then end of character in 'last' + // returns 'are there more characters in string?' + // if there are no more characters, will return 0 and first = last = end + static bool PeekNextChar( const TSTRING::const_iterator& cur, + const TSTRING::const_iterator& end, + TSTRING::const_iterator& first, + TSTRING::const_iterator& last ); + + // same as PeekNextChar but increments 'cur' to 'last' + static bool PopNextChar( TSTRING::const_iterator& cur, + const TSTRING::const_iterator& end, + TSTRING::const_iterator& first, + TSTRING::const_iterator& last ); +}; + +#endif//__CHARUTIL_H + diff --git a/src/core/charutil_t.cpp b/src/core/charutil_t.cpp new file mode 100644 index 0000000..e22828f --- /dev/null +++ b/src/core/charutil_t.cpp @@ -0,0 +1,105 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: charutil_t.cpp +// Date....: 10/22/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdcore.h" + +#ifdef TSS_TEST + +#include "test/utx.h" +#include "charutil.h" +#include "debug.h" +#include "errorbucketimpl.h" + + +/////////////////////////////////////////////////////////////////////////////// +// cCharEncoderTest +/////////////////////////////////////////////////////////////////////////////// +class cCharEncoderTest +{ +public: + + void PrintChars( const TSTRING& str ) + { + const TCHAR* cur = str.begin(); + const TCHAR* end = str.end(); + const TCHAR* first = NULL; + const TCHAR* last = NULL; + + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + TCOUT << _T("char length: ") << (int)(last - first) << std::endl; + + TCOUT << _T("char: <"); + for( const TCHAR* at = first; at != last; at++ ) + { + if( at != first ) + TCOUT << _T(","); + TCOUT << (int)*at; + } + TCOUT << _T(">") << std::endl; + } + + TCOUT << _T("----------------------------") << std::endl; + } + + /////////////////////////////////////////////////////////////////////////// + // Basic + /////////////////////////////////////////////////////////////////////////// + void Basic( tss::TestContext& ctx ) + { + try + { + PrintChars( _T("foo") ); + PrintChars( _T("fo\x2354") ); + } + catch( eError& e ) + { + cErrorReporter::PrintErrorMsg( e ); + ASSERT(false); + } + } +}; + +TSS_BeginTestSuiteFrom( cCharEncoderTest ) + + TSS_AddTestCase( Basic ); + +TSS_EndTestSuite( cCharEncoderTest ) + +#endif // TSS_TEST + +// eof: charutil_t.cpp diff --git a/src/core/cmdlineparser.cpp b/src/core/cmdlineparser.cpp new file mode 100644 index 0000000..c6f154b --- /dev/null +++ b/src/core/cmdlineparser.cpp @@ -0,0 +1,472 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// cmdlineparser.cpp +#include "stdcore.h" +#include "cmdlineparser.h" +#include "corestrings.h" + + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dotr +/////////////////////////////////////////////////////////////////////////////// +cCmdLineParser::cCmdLineParser() : + mArgTable(HASH_VERY_SMALL), + mLastArgInfo(-1, PARAM_NONE) +{ +} + +cCmdLineParser::~cCmdLineParser() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// AddArg +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::AddArg(int argId, const TSTRING& arg, const TSTRING& alias, ParamCount numParams, bool multipleAllowed) +{ + if(arg.empty() && alias.empty()) + { + // this refers to the list of parameters that comes after all the cmd line switches + mLastArgInfo.mId = argId; + mLastArgInfo.mNumParams = numParams; + return ; + } + + if(! arg.empty()) + mArgTable.Insert(arg, cArgInfo(argId, numParams)); + if(! alias.empty()) + { + // put the alias in the table with a '-' prepended to it so it matches '--' + TSTRING str(_T("-")); + str += alias; + mArgTable.Insert(str, cArgInfo(argId, numParams)); + } + // This argument can appear more than once on the command line. + if( multipleAllowed ) + mMultipleAllowed.insert( argId ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::Clear() +{ + mLastArgInfo.mId = -1; + mLastArgInfo.mNumParams = PARAM_INVALID; + mArgTable.Clear(); + mArgData.clear(); + mMutExList.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Parse +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::Parse(int argc, const TCHAR *const * argv) +{ + // clear out any existing data + mArgData.clear(); + + const TCHAR* pCurArg = 0; + bool bProcessedFinalParams = false; // gets set to true when the parameters to the command line are processed + + // I assume argv[0] is the executable name... + for(int i=1; i < argc; i++) + { + if(argv[i][0] == _T('-')) + { + pCurArg = argv[i]; + + // this is a switch; find it in the table... + cArgInfo argInfo; + if ( !mArgTable.Lookup( TSTRING(&argv[i][1] ), argInfo ) ) + { + // unknown switch! + throw eCmdLineInvalidArg( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + pCurArg ); + } + // + // make sure this hasn't been specified yet... + // + if( ArgInList( argInfo.mId ) ) + { + // Make sure it isn't okay for this one to appear more than once... + std::set::iterator it = mMultipleAllowed.find( argInfo.mId ); + if( it == mMultipleAllowed.end() ) + { + // It wasn't in our list of allowed params, so error. + throw eCmdLineMultiArg( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + argv[i] ); + } + } + // + // add it to the list.. + // + mArgData.push_back(cArgData(argInfo.mId, TSTRING(argv[i]))); + cArgData& curArg = mArgData.back(); + switch( argInfo.mNumParams ) + { + case PARAM_NONE: + // make sure there are no parameters to this, but be careful because + // it is legal to start the parameters to the executable here. + if((i+1 < argc) && (argv[i+1][0] != _T('-'))) + { + // search for any more parameters + // TODO: In the future we may want to support a '--' switch that specifies the start + // of parameters to the executable. + for (int j = i + 2; j < argc; ++j ) + { + if (argv[j][0] == _T('-')) + { + // >0 parameter passed ! + throw eCmdLineBadParam( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + pCurArg ); + } + } + } + break; + + case PARAM_ONE: + // get the next parameter... + i++; + if ( (i >= argc) || (argv[i][0] == _T('-')) ) + { + // zero parameters passed to something that needed one param + throw eCmdLineBadParam( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + pCurArg ); + } + + curArg.mParams.push_back( TSTRING(argv[i]) ); + break; + + case PARAM_MANY: + i++; + while((i < argc) && (argv[i][0] != _T('-'))) + { + curArg.mParams.push_back(TSTRING(argv[i])); + i++; + } + i--; // since we have gone too far at this point + break; + + default: + ASSERTMSG( false, "Unknown number of arguments to parser" ); + } + } + else + { + bProcessedFinalParams = true; + // this must be the final "unnamed" arg + // first, make sure it is consistent with the current info... + bool bResult = true; + switch(mLastArgInfo.mNumParams) + { + case PARAM_NONE: + // this is an error; they didn't want any command line parameters... + bResult = false; + break; + case PARAM_ONE: + if(i+1 != argc) + // there is >1 final parameter; it is an error + bResult = false; + break; + case PARAM_MANY: + // we'll catch errors below + break; + default: + ASSERT(false); + + } + if(! bResult) + { + throw eCmdLineBadParam( ); + } + + // ok, we can push the final parameter info onto the list... + mArgData.push_back(cArgData(mLastArgInfo.mId)); + cArgData& curArg = mArgData.back(); + + while ( i < argc ) + { + if ( argv[i][0] == _T('-') ) + { + if ( ! pCurArg ) + { + throw eCmdLineBadSwitchPos( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + argv[i] ); + } + else + { + // there was an extra parameter passed somewhere! + throw eCmdLineBadArgParam( + TSS_GetString( cCore, core::STR_ERR2_BAD_ARG_PARAMS ) + + pCurArg ); + } + } + + // add this param to the list + curArg.mParams.push_back(TSTRING(argv[i])); + i++; + } + + + } + + } + + // it is possible not to process the final command line parameters in the "else" case above + // (this only occurs if there are no command line parameters specified) so let's make sure that + // is consistent with what we are configured with... + // NOTE -- it is ok to have no cmd line parameters if they specified PARAM_NONE or PARAM_MANY + if(! bProcessedFinalParams) + { + if(mLastArgInfo.mNumParams == PARAM_ONE) + { + throw eCmdLineBadParam( ); + } + } + + // Check for "relationship errors": + TestMutEx(); + TestDependency(); +} + +/////////////////////////////////////////////////////////////////////////////// +// TestMutEx +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::TestMutEx() +{ + std::list >::const_iterator i; + cCmdLineIter iter1(*this), iter2(*this); + for(i = mMutExList.begin(); i != mMutExList.end(); i++) + { + //TODO -- there is a much more efficent way to do this (using cFCOPropVector, for example) + // the command line is presumably small enough, tho, that it probably isn't a big + // deal to do it this way. + iter1.SeekToArg(i->first); + if(! iter1.Done()) + { + iter2.SeekToArg(i->second); + if(! iter2.Done()) + { + // we have a mutual exclusion violation! + throw eCmdLineMutEx( + iter1.ActualParam() + + _T(", ") + + iter2.ActualParam() ); + } + } + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// TestDependency +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::TestDependency() +{ + std::list< std::pair< std::pair< int, int>, bool > >::const_iterator i; + cCmdLineIter iter1(*this), iter2(*this); + + for( i = mDependencyList.begin(); i != mDependencyList.end(); ++i) + { + iter1.SeekToArg( i->first.first ); + // was it on the command line? + if( !iter1.Done() ) + { + // it was, is the corresponding arg on the command line? + iter2.SeekToArg( i->first.second ); + if( iter2.Done() ) // it wasn't, dependency error + { + TSTRING arg1, arg2, alias1, alias2; + cCmdLineParser::LookupArgInfo( i->first.first, arg1, alias1 ); + cCmdLineParser::LookupArgInfo( i->first.second, arg2, alias2 ); + + // determine in which form the user passed the arguments, + // and construct the error message in the same form + if ( iter1.ActualParam().length() == 2 ) + throw eCmdLineDependency( _T("The switch -") + arg1 + _T(" requires -") + arg2 +_T(".") ); + else + throw eCmdLineDependency( _T("The switch --") + alias1 + _T(" requires --") + alias2 + _T(".") ); + } + } + else if( i->second ) + // only make this second check if the dependencies are MUTUAL, + // as indicated (or not) by the bool value. + { + iter2.SeekToArg( i->first.second ); + // the first arg in the pair was not on the command line, + // so just make sure the second isn't there... + if( !iter2.Done() ) + { + // arg2 appeared without arg1, so dependency error. + TSTRING arg1, arg2, alias1, alias2; + cCmdLineParser::LookupArgInfo( i->first.first, arg1, alias1 ); + cCmdLineParser::LookupArgInfo( i->first.second, arg2, alias2 ); + + // determine in which form the user passed the arguments, + // and construct the error message in the same form + if ( iter1.ActualParam().length() == 2 ) + throw eCmdLineDependency( _T("The switch -") + arg2 + _T(" requires -") + arg1 +_T(".") ); + else + throw eCmdLineDependency( _T("The switch --") + alias2 + _T(" requires --") + alias1 + _T(".") ); + } + } + + } //end for +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddMutEx +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::AddMutEx(int argId1, int argId2) +{ + // note that I do no checking for duplicates here... + std::pair mutEx(argId1, argId2); + ASSERT(argId1 != argId2); + mMutExList.push_back(mutEx); +} + +/////////////////////////////////////////////////////////////////////////////// +// AddDependency +/////////////////////////////////////////////////////////////////////////////// +void cCmdLineParser::AddDependency(int argId1, int argId2, bool mutual ) +{ + // again, no checking for duplicates... would a set + // prove to be a better container for this operation? + std::pair< int, int > Args( argId1, argId2 ); + std::pair< std::pair< int, int >, bool > Dep( Args, mutual ); + + ASSERT(argId1 != argId2); + mDependencyList.push_back( Dep); +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +#ifdef _DEBUG +void cCmdLineParser::TraceContents(int dl) +{ + cDebug d("cCmdLineParser::TraceContents"); + if(dl == -1) + dl = cDebug::D_DEBUG; + + std::list::const_iterator i; + for(i = mArgData.begin(); i != mArgData.end(); i++) + { + d.Trace(dl, "* Item id:%d\n", i->mId); + for(std::vector::const_iterator vi = i->mParams.begin(); vi != i->mParams.end(); vi++) + { + d.Trace(dl, "\t%s\n", vi->c_str()); + } + } + + d.Trace(dl, "--- Switch id table ---\n"); + + cHashTableIter iter(mArgTable); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + d.Trace(dl, "[%d] %s\n", iter.Val().mId, iter.Key().c_str()); + } + + d.Trace(dl, "[%d] Final Param List\n", mLastArgInfo.mId); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// LookupArgInfo +/////////////////////////////////////////////////////////////////////////////// +bool cCmdLineParser::LookupArgInfo(int argId, TSTRING& arg, TSTRING& alias) const +{ + arg = _T(""); + alias = _T(""); + + cHashTableIter iter(mArgTable); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + if(iter.Val().mId == argId) + { + TSTRING str = iter.Key(); + if((str.length() > 0) && (str[0] == _T('-'))) + { + // this is the alias! + alias = (str.c_str() + 1); + } + else + { + // this is the arg... + arg = str; + } + } + } + return ((! arg.empty()) || (! alias.empty())); +} + +/////////////////////////////////////////////////////////////////////////////// +// ArgInList +/////////////////////////////////////////////////////////////////////////////// +bool cCmdLineParser::ArgInList(int argId) +{ + std::list::iterator i; + for( i = mArgData.begin(); i != mArgData.end(); i++ ) + { + if( i->mId == argId ) + return true; + } + return false; +} + + +//############################################################################# +// cCmdLineIter +//############################################################################# + +/////////////////////////////////////////////////////////////////////////////// +// SeekToArg +/////////////////////////////////////////////////////////////////////////////// +bool cCmdLineIter::SeekToArg(int argId) const +{ + for(SeekBegin(); ! Done(); Next()) + { + if(ArgId() == argId) + return true; + } + + return false; + +} + diff --git a/src/core/cmdlineparser.h b/src/core/cmdlineparser.h new file mode 100644 index 0000000..3957d6b --- /dev/null +++ b/src/core/cmdlineparser.h @@ -0,0 +1,267 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// cmdlineparser.h +// +// cCmdLineParser.h -- class that tokenizes the command line +#ifndef __CMDLINEPARSER_H +#define __CMDLINEPARSER_H + +#ifndef __HASHTABLE_H +#include "hashtable.h" +#endif +#ifndef __DEBUG_H +#include "debug.h" +#endif +#ifndef __ERROR_H +#include "error.h" +#endif + +//============================================================================= +// eCmdLine +//============================================================================= +TSS_EXCEPTION( eCmdLine, eError ) +TSS_EXCEPTION( eCmdLineInvalidArg, eCmdLine ) // an arg on the command line is not recognized +TSS_EXCEPTION( eCmdLineBadArgParam, eCmdLine ) // wrong number of parameters to an argument +TSS_EXCEPTION( eCmdLineBadParam, eCmdLine ) // wrong number of paramters to the executable (not associated with any arguments) +TSS_EXCEPTION( eCmdLineBadSwitchPos,eCmdLine ) // a '-' arg appeared after the final parameter list +TSS_EXCEPTION( eCmdLineMutEx, eCmdLine ) // a mutual exclusion error has occured +TSS_EXCEPTION( eCmdLineDependency, eCmdLine ) // a dependency error has occurred. +TSS_EXCEPTION( eCmdLineMultiArg, eCmdLine ) // an arg was found twice in the command line + + +/* + // cCmdLineParser owns errors 600-699 + // these can be turned into a string by using cErrorTable + enum ErrorType + { + ERR_NONE = 601, // no error + ERR_INVALID_ARG = 602, // an arg on the command line is not recognized + ERR_BAD_ARG_PARAMS = 603, // wrong number of parameters to an argument + ERR_BAD_PARAMS = 604, // wrong number of paramters to the executable (not associated with any arguments) + ERR_SWITCH_AFTER_FINAL_LIST = 605, // a '-' arg appeared after the final paramter list + ERR_MUTUAL_EXCLUSION = 606, // a mutual exclusion error has occured + ERR_MULTIPLE_ARG = 607, // an arg was found twice in the command line + + ERR_INVALID // top of enum + }; + + // for storing error information + ErrorType mCurError; + TSTRING mCurErrorString; + void GetErrorInfo(ErrorType& et, TSTRING& errorData) const; + // returns information on the type of error that occured in a Parse() command. Only + // returns valid information if Parse() had just been called and returned false. A + // second call to Parse() might alter existing error info +*/ + +//============================================================================= +// cCmdLineParser +//============================================================================= +class cCmdLineParser +{ +public: + cCmdLineParser(); + ~cCmdLineParser(); + + enum ParamCount + { + PARAM_NONE, // no parameters to arg + PARAM_ONE, // one parameter to arg + PARAM_MANY, // zero or more paramters to arg + + PARAM_INVALID // top of enum + }; + + void AddArg(int argId, const TSTRING& arg, const TSTRING& alias, ParamCount numParams, bool multipleAllowed = false); + // this method should be called for each argument that can appear on the + // command line. + // argId -- a number that uniquely identifies the argument; no two arguments + // may have the same id (ASSERT-enforced) + // arg -- string that comes after the '-'. can be _T("") if there is only + // a string representation + // alias -- string that comes after '--' which has the same meaning. Can be _T("") + // if there is no alias. If both arg and alias are empty strings, then this arg + // represents the list of arguments that comes at the end of the command line + // numParams -- number of parameters that this argument needs + + void AddMutEx(int argId1, int argId2); + // this adds a mutual exclusion constraint. When Parse() is called, if argId1 and + // argId2 both exist on the command line, then the parse will fail and the error + // value ERR_MUTUAL_EXCLUSION will be set. + + void AddDependency(int argId1, int argId2, bool mutual = false ); + // This adds a dependency constraint. When Parse() is called, if argId1 + // exists on the command line independent from argId2, then the parse will fail. + // If the default param mutual is true, then the command parser will check for + // argId1 if argId2 is passed. We do this, since it is possible for one arg to + // depend on another, but have the other arg alone on the command line, legally. + + void Parse(int argc, const TCHAR *const * argv); // throw eCmdLine + // after AddArg() has been called for every argument that could be processed by the + // command line, call this to tokenize argv. If the return value is false, then + // the input was invalid in some way; the actual error can be determined by calling + // GetErrorInfo() below. + + void Clear(); + // clear out all information that this class contains + + bool LookupArgInfo(int argId, TSTRING& arg, TSTRING& alias) const; + // given an argId, fill out the strings with the argument and alias strings. Returns false + // if the argId cannot be found. This method is not very fast, so don't use it often. + + #ifdef _DEBUG + void TraceContents(int dl = -1) ; + #endif +private: + void TestMutEx(); + // tests for mutual exclusion violations; if it fails, the current error is set and false + // is returned. + void TestDependency(); + // tests for all dependency violations. + bool ArgInList(int argId); + // returns true if an argument with the specified id already exists in the list; this is used + // to make sure the same arg doesn't appear >1 time on the command line + + // for storing information on paramers + struct cArgInfo + { + int mId; + ParamCount mNumParams; + + cArgInfo(int i = -1, ParamCount p = PARAM_INVALID) : mId(i), mNumParams(p) {} + }; + // for storing parsed argv information + struct cArgData + { + int mId; + std::vector mParams; + TSTRING mActualParam; // a string representation of what was actually on the command line + + cArgData(int id = -1, const TSTRING& actualParam = TSTRING(_T(""))) : mId(id), mActualParam(actualParam) {} + }; + + cHashTable mArgTable; + cArgInfo mLastArgInfo; // info on the argument that comes at the end of the command line (with no associated '-x' or '--x') + std::list mArgData; + std::list > mMutExList; // all of the mutual exclusions + std::list< std::pair < std::pair, bool > > mDependencyList; // all of the dependencies + std::set< int > mMultipleAllowed; + + friend class cCmdLineIter; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cCmdLineIter -- used to iterate over the tokenized command line parameters; +// is only useful after cCmdLineParser::Parse() has been called. +/////////////////////////////////////////////////////////////////////////////// +class cCmdLineIter +{ +public: + cCmdLineIter(const cCmdLineParser& parser); + + // iteration + void SeekBegin() const; + bool Done() const; + bool IsEmpty() const; + void Next() const; + + bool SeekToArg(int argId) const; + // seeks to the argument with the given argId. returns + // false and Done() == true if it couldn't find it. + + // access to the argument data + int ArgId() const; + // returns the id of this arg; ASSERTs if Done() == true + int NumParams() const; + // returns the number of parameters this argument has + const TSTRING& ActualParam() const; + // returns exactly what was passed on the command line (ie -- what the user typed) + const TSTRING& ParamAt(int index) const; + // returns the parameter at the specified index. ASSERTs if + // the index is out of range. + +private: + const std::list& mList; + mutable std::list::const_iterator mIter; +}; + +//############################################################################# +// inline implementation +//############################################################################# +inline cCmdLineIter::cCmdLineIter(const cCmdLineParser& parser) : + mList(parser.mArgData) +{ + SeekBegin(); +} +inline void cCmdLineIter::SeekBegin() const +{ + mIter = mList.begin(); +} +inline bool cCmdLineIter::Done() const +{ + return (mIter == mList.end()); +} +inline bool cCmdLineIter::IsEmpty() const +{ + return (mList.size() == 0); +} +inline void cCmdLineIter::Next() const +{ + mIter++; +} +inline int cCmdLineIter::ArgId() const +{ + ASSERT(! Done()); + return mIter->mId; +} +inline int cCmdLineIter::NumParams() const +{ + ASSERT(! Done()); + return mIter->mParams.size(); +} + +inline const TSTRING& cCmdLineIter::ActualParam() const +{ + ASSERT(! Done()); + return mIter->mActualParam; +} + +inline const TSTRING& cCmdLineIter::ParamAt(int index) const +{ + ASSERT((index >= 0) && (index < NumParams())); + return mIter->mParams[index]; +} + + +#endif + diff --git a/src/core/cmdlineparser_t.cpp b/src/core/cmdlineparser_t.cpp new file mode 100644 index 0000000..ccf2915 --- /dev/null +++ b/src/core/cmdlineparser_t.cpp @@ -0,0 +1,178 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// cmdlineparser_t.cpp + +#include "stdcore.h" +#include "cmdlineparser.h" +#include "test/test.h" +//#include "tw/twutil.h" +//#include "tw/twstrings.h" + +const int argc1 = 9; +const TCHAR* argv1[] = +{ + _T("tripwire.exe"), + _T("-m"), + _T("Init"), + _T("-tp"), + _T("one"), + _T("two"), + _T("--verbose"), + _T("frog"), + _T("cat") +}; + +const int argc2 = 3; +const TCHAR* argv2[] = +{ + _T("tripwire.exe"), + _T("-m"), + _T("-v") +}; + +const int argc3 = 3; +const TCHAR* argv3[] = +{ + _T("tripwire.exe"), + _T("dog"), + _T("-v"), +}; + +// test with the last param wanting 1 or 0 parameters :-) +const int argc4 = 5; +const TCHAR* argv4[] = +{ + _T("tripwire.exe"), + _T("-tp"), + _T("-v"), + _T("frog"), + _T("cat") +}; + +const int argc5 = 4; +const TCHAR* argv5[] = +{ + _T("tripwire.exe"), + _T("-tp"), + _T("-v"), + _T("frog") +}; + +static void PrintCmdLine(int argc, const TCHAR** argv, cDebug d) +{ + TSTRING str; + d.TraceDebug("Testing command line:\n"); + for(int i=0; i < argc; i++) + { + str += argv[i]; + str += _T(" "); + } + d.TraceDebug(_T(">>>%s\n"), str.c_str()); +} + +void TestCmdLineParser() +{ + enum ArgId { ID_M, ID_TP, ID_V, ID_UNNAMED }; + + try { + cCmdLineParser p; + p.AddArg(ID_M, TSTRING(_T("m")), TSTRING(_T("mode")), cCmdLineParser::PARAM_ONE); + p.AddArg(ID_TP, TSTRING(_T("tp")), TSTRING(_T("twoparam")), cCmdLineParser::PARAM_MANY); + p.AddArg(ID_V, TSTRING(_T("v")), TSTRING(_T("verbose")), cCmdLineParser::PARAM_NONE); + p.AddArg(ID_UNNAMED, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); + + cDebug d("TestCmdLineParser"); + + PrintCmdLine(argc1, argv1, d); + p.Parse(argc1, argv1); + #ifdef _DEBUG + p.TraceContents(); + #endif + + PrintCmdLine(argc2, argv2, d); + p.Parse(argc2, argv2); // should fail. + #ifdef _DEBUG + p.TraceContents(); + #endif + + PrintCmdLine(argc3, argv3, d); + p.Parse(argc3, argv3); // should fail + #ifdef _DEBUG + p.TraceContents(); + #endif + + PrintCmdLine(argc4, argv4, d); + p.Parse(argc4, argv4); + #ifdef _DEBUG + p.TraceContents(); + #endif + + /* + // TODO - test mutual exclusion... + + cCmdLineParser::ErrorType et; + TSTRING errStr; + d.TraceDebug("** Making -m and -v mutually exclusive, then running on first cmd line...\n"); + p.AddMutEx(ID_M, ID_V); + p.Parse(argc1, argv1); // should fail + p.GetErrorInfo(et, errStr); + TEST(et == cCmdLineParser::ERR_MUTUAL_EXCLUSION); + d.TraceDebug(_T("Mutual exclusion test worked; here is the error string: %s\n"), errStr.c_str()); + */ + + // make the command line want one parameter + d.TraceDebug("** Changing cmd line to only want one last param...\n"); + p.AddArg(ID_UNNAMED, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + PrintCmdLine(argc4, argv4, d); + p.Parse(argc4, argv4); // should fail + #ifdef _DEBUG + p.TraceContents(); + #endif + + PrintCmdLine(argc5, argv5, d); + p.Parse(argc5, argv5); + #ifdef _DEBUG + p.TraceContents(); + #endif + + + // TODO -- test a bunch more!!! + } + catch (eCmdLine &e) + { + TCERR << _T("Command line error: "); + TCERR << e.GetMsg() << std::endl; + TEST(false); + } +} + diff --git a/src/core/codeconvert.cpp b/src/core/codeconvert.cpp new file mode 100644 index 0000000..727c2c7 --- /dev/null +++ b/src/core/codeconvert.cpp @@ -0,0 +1,1544 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: codeconvert.cpp +// Date....: 9/2/99 +// Creator.: Brian McFeely (bmcfeely) +// +// Convert a string between locale NTMBS encoding and UCS2 +// + + +/// Requirements + +#include "stdcore.h" // for: pch +#include "core/codeconvert.h" // for: These classes +#include "corestrings.h" // for: Error Strings +#include "fsservices.h" // for: strerror +#include "ntmbs.h" +#include "errno.h" + + +#ifdef DEBUG +#define TSS_CCONV_VERBOSE // Uncomment for verbose tracing! +#endif + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// DEFINES +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/* + * ICONV conversion seems to be broken under Linux, so until + * this is fixed, we'll wing it ourselves - 20010310 PH + */ +#if 0 +#define TSS_USE_ICONV_CCONV16 HAVE_ICONV_H +#define TSS_USE_UCS2_CCONV16 (!(HAVE_ICONV_H) && WCHAR_REP_IS_UCS2 && WCHAR_IS_16_BITS) +#define TSS_USE_UCS2_CCONV32 (!(HAVE_ICONV_H) && WCHAR_REP_IS_UCS2 && WCHAR_IS_32_BITS) +#else +#define TSS_USE_UCS2_CCONV16 (WCHAR_REP_IS_UCS2 && WCHAR_IS_16_BITS) +#define TSS_USE_UCS2_CCONV32 (WCHAR_REP_IS_UCS2 && WCHAR_IS_32_BITS) +#endif + + #define ICONV_SOURCE_TYPE const char + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Static Data +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +iCodeConverter* iCodeConverter::m_pInst = NULL; + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// iCodeConverter +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// has a maximum of 512 chars of output +std::string util_output_bytes( void* p, size_t n ) +{ + std::ostringstream ss; + ss.imbue( std::locale::classic() ); + ss.setf( std::ios_base::hex, std::ios_base::basefield ); + + for( size_t i = 0; i < n; i++ ) + { + ss.width( 2 ); + ss << toupper( tss::util::char_to_size( ((char*)p)[i] ) ) << " "; + } + + std::string s = ss.str(); + if( s.length() > 512 ) + { + s = "truncated output: " + s; + s.resize( 512 ); + } + + return s; +} + +iCodeConverter* iCodeConverter::GetInstance() +{ + if( ! m_pInst ) + { + m_pInst = CreateConverter(); + } + + ASSERT( m_pInst ); + return m_pInst; +} + +iCodeConverter* iCodeConverter::CreateConverter() +{ + cDebug d("iCodeConverter::CreateConverter()"); + +#if TSS_USE_ICONV_CCONV16 + + if( cIconvConverter::Test() ) + { + d.TraceDebug("using cIconvConverter\n"); + return new cIconvConverter; + } + else if( cDoubleIconvConverter::Test() ) + { + d.TraceDebug("using cDoubleIconvConverter\n"); + return new cDoubleIconvConverter; + } + else + { + d.TraceDebug("using CreateGoodEnoughConverter\n"); + return CreateGoodEnoughConverter(); + } + +#elif TSS_USE_UCS2_CCONV32 + + d.TraceDebug("using cWcharIs32BitUcs2Converterer\n"); + return new cWcharIs32BitUcs2Converterer; + +#elif TSS_USE_UCS2_CCONV16 + + d.TraceDebug("using cWcharIs16BitUcs2Converterer\n"); + return new cWcharIs16BitUcs2Converterer; + +#else // we don't have a proper converter, so fudge a little... + + d.TraceDebug("using CreateGoodEnoughConverter\n"); + return CreateGoodEnoughConverter(); + +#endif + + ASSERT( ! "reachable" ); +} + + +iCodeConverter* iCodeConverter::CreateGoodEnoughConverter() +{ + // + // let someone know that we don't work on non-english OSs... + // + cDebug d( "iCodeConverter::CreateGoodEnoughConverter()" ); + d.TraceAlways( "database WILL NOT be portable to other platforms.\n" ); + + return new cGoodEnoughConverterer; +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// iconv Converters +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#if TSS_USE_ICONV_CCONV16 + +#include +#include + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Module Locale Helpers for iconv() +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "core/ntmbs.h" + +namespace /*Unique*/ +{ + void tss_dispatch_iconvopen_error() + { + cDebug d("tss_dispatch_iconvopen_error"); + + switch( errno ) + { + case EMFILE: + d.TraceDebug( "EMFILE: {OPEN_MAX} files descriptors are currently open in the calling process..\n" ); + break; + case ENFILE: + d.TraceDebug( "ENFILE: Too many files are currently open in the system.\n" ); + break; + case ENOMEM: + d.TraceDebug( "ENOMEM: Insufficient storage space is available.\n" ); + break; + case EINVAL: + d.TraceDebug( "EINVAL: The conversion specified by fromcode and tocode is not supported by the implementation.\n" ); + break; + default: + d.TraceDebug( "UNKNOWN: Unknown error.\n" ); + break; + } + } + + int tss_dispatch_errno( cDebug& d ) + { + // Reasons for failure: + // [EILSEQ] Input conv stopped due to an unknown input byte + // [E2BIG] Input conversion stopped due to lack of space in the output + // [EINVAL] Input conversion stopped due to an incomplete character + // [EBADF] The cd argument is not a valid open conversion descriptor. + // errno + d.TraceDebug( + _T( "iconv failed with: %s\n" ), + iFSServices::GetInstance()->GetErrString().c_str() ); + + /// RAD: Always throw on error (Let user Catch if they want to go on) + switch ( errno ) + { + case EILSEQ: + case EINVAL: + throw + eConverterFatal ( + TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + break; + + case E2BIG: + throw + eConverterFatal( + TSS_GetString(cCore, core::STR_ERR_OVERFLOW ) ); + break; + + case EBADF: + throw + eConverterUnknownCodepage( + TSS_GetString( cCore, core::STR_UNKNOWN ) ); + break; + + default: + throw + eConverterFatal( + TSS_GetString( cCore, core::STR_UNKNOWN ) ); + } + + return -1; + } + + template< class BufferT, class SourceT > + class ByteConvert + { + public: + + bool + Convert( BufferT** ppBuf, size_t* pnBufferLeft, + const SourceT** ppSrc, size_t* pnSourceLeft ) + { + cDebug d( "ByteConvert::Convert< BufferT, SourceT >()" ); + + //-- Copy manually into Buffer + **ppBuf = cConvertUtil::ConvertNonChar( **ppSrc ); + + //-- Decrement counters + *pnSourceLeft -= sizeof(SourceT); // Decrement Source Left + *pnBufferLeft -= sizeof(BufferT); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc)++; // Skip one SourceT fwd + (*ppBuf)++; // Skip one BufferT fwd + + return true; + } + }; + + + class UTF8_Util + { + public: + enum { INVALID_VALUE = 0xFF }; + }; + + // convert to INVALID_VALUE and remember the byte value + template< class BufferT, class SourceT > + class ToUTF8Convert + { + public: + + ToUTF8Convert( std::list& lb ) + : m_lb( lb ) {} + + bool + Convert( mbchar_t** ppBuf, size_t* pnBufferLeft, + const dbchar_t** ppSrc, size_t* pnSourceLeft ) + { + cDebug d( "ToUTF8Convert::Convert< mbchar_t, dbchar_t >()" ); + + // store the non char value + m_lb.push_back( cConvertUtil::ConvertNonChar( **ppSrc ) ); + + // flag 'invalid char' + **ppBuf = (mbchar_t)UTF8_Util::INVALID_VALUE; + + //-- Decrement counters + *pnSourceLeft -= sizeof(dbchar_t); // Decrement Source Left + *pnBufferLeft -= sizeof(mbchar_t); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc)++; // Skip one SourceT fwd + (*ppBuf)++; // Skip one BufferT fwd + + return true; + } + + bool + Convert( mbchar_t** ppBuf, size_t* pnBufferLeft, + const mbchar_t** ppSrc, size_t* pnSourceLeft ) + { + cDebug d( "ToUTF8Convert::Convert< char, char >()" ); + + // store non-char value + m_lb.push_back( **ppSrc ); + + // flag 'invalid char' + **ppBuf = (char)UTF8_Util::INVALID_VALUE; + + //-- Decrement counters + *pnSourceLeft -= sizeof(mbchar_t); // Decrement Source Left + *pnBufferLeft -= sizeof(mbchar_t); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc)++; // Skip one SourceT fwd + (*ppBuf)++; // Skip one BufferT fwd + + return true; + } + + private: + + // TODO:Get rid of this guy and just use a vector and + // insert them when finished with second step + std::list& m_lb; + }; + + template< class BufferT, class SourceT > + class FromUTF8Convert + { + public: + + FromUTF8Convert( std::list& lb ) + : m_lb( lb ) {} + + bool + Convert( dbchar_t** ppBuf, size_t* pnBufferLeft, + const mbchar_t** ppSrc, size_t* pnSourceLeft ) + { + cDebug d( "FromUTF8Convert::Convert< dbchar_t, mbchar_t >()" ); + + //-- Must be our flag char + size_t value = tss::util::char_to_size( **ppSrc ); + if ( value != (size_t)UTF8_Util::INVALID_VALUE ) + { + d.TraceDebug( "value was not flag char: %X...\n", value ); + return false; + } + + //-- Get correct character from our byte array + ASSERT( ! m_lb.empty() ); + mbchar_t newVal = (mbchar_t)tss::util::char_to_size( m_lb.front() ); + m_lb.pop_front(); + + //-- Copy character + d.TraceDebug( "converted to: %X\n", tss::util::char_to_size( newVal ) ); + **ppBuf = cConvertUtil::ConvertNonChar( newVal ); + + //-- Decrement counters + *pnSourceLeft -= sizeof(mbchar_t); // Decrement Source Left + *pnBufferLeft -= sizeof(dbchar_t); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc)++; // Skip one mbchar_t fwd + (*ppBuf)++; // Skip one dbchar_t fwd + + return true; + } + + // Converts a UTF-8 value to corresponding UCS2 char (in the private + // use range) whose value is 0xE000 < x < 0xE0FF in UCS2. + // Must be of the form 11101110 100000xx 10xxxxxx + bool + Convert( mbchar_t** ppBuf, size_t* pnBufferLeft, + const mbchar_t** ppSrc, size_t* pnSourceLeft ) + { + cDebug d( "FromUTF8Convert::Convert< mbchar_t, mbchar_t >()" ); + /* + const size_t NUM_CHARS = 3; + + //-- Must be our cast byte value + if( *pnBufferLeft < NUM_CHARS ) + { + d.TraceDebug( "not enough buffer space to be our cast byte: %d\n", *pnBufferLeft ); + return false; + } + + size_t first = tss::util::char_to_size( (*ppSrc)[0] ); + size_t second = tss::util::char_to_size( (*ppSrc)[1] ); + size_t third = tss::util::char_to_size( (*ppSrc)[2] ); + + d.TraceDebug( "have: first: 0x%08X, second: 0x%08X, third: 0x%08X\n", + first, second, third ); + + //-- We expect the value to be UCS2_RESERVED_START + [0x00,0xFF] + // ( 0xE000 - 0xE0FF ) which would be of the form + // 11101110 100000xx 10xxxxxx in UTF-8 + if( ( first != 0xEEu ) || + ( ( second & 0xFCu ) != 0x80u ) || + ( ( third & 0xC0u ) != 0x80u ) ) + { + d.TraceDebug( "Value was not UTF-8 for a char <= 0xE0FF and > 0xE000\n" ); + return false; + } + + //-- Get value of character + size_t newVal = ( ( second & 0x03u ) << 6 ) | ( third & 0x3Fu ); + + if( ( newVal > ( UTF8_Util::UCS2_RESERVED_START + 0xFF ) ) || + ( newVal < UTF8_Util::UCS2_RESERVED_START ) ) + { + d.TraceDebug( "value was not in our private use range: %X...\n", newVal ); + return false; + } + + //-- Remove offset + newVal -= UTF8_Util::UCS2_RESERVED_START; + ASSERT( newVal <= 0xFF ); + + //-- Copy character + d.TraceDebug( "converted to: %X\n", newVal ); + **ppBuf = (mbchar_t)newVal; + + //-- Decrement counters + *pnSourceLeft -= NUM_CHARS * sizeof(mbchar_t); // Decrement Source Left + *pnBufferLeft -= sizeof(mbchar_t); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc) += NUM_CHARS; // Skip two chars fwd + (*ppBuf) += 1; // Skip one char fwd + + return true; + */ + + //-- Must be our flag char + size_t value = tss::util::char_to_size( **ppSrc ); + if ( value != (size_t)UTF8_Util::INVALID_VALUE ) + { + d.TraceDebug( "value was not flag char: %X...\n", value ); + return false; + } + + //-- Get correct character from our byte array + ASSERT( ! m_lb.empty() ); + mbchar_t newVal = (mbchar_t)tss::util::char_to_size( m_lb.front() ); + m_lb.pop_front(); + + //-- Copy character + d.TraceDebug( "converted to: %X\n", tss::util::char_to_size( newVal ) ); + **ppBuf = newVal; + + //-- Decrement counters + *pnSourceLeft -= sizeof(mbchar_t); // Decrement Source Left + *pnBufferLeft -= sizeof(mbchar_t); // Decrement Buffer Left + + //-- Reposition pointers + (*ppSrc)++; // Skip one mbchar_t fwd + (*ppBuf)++; // Skip one dbchar_t fwd + + return true; + } + + private: + + // TODO:Get rid of this guy and just use a vector and + // insert them when finished with second step + std::list& m_lb; + }; + + bool + tss_ReverseConvert( iconv_t revConv, + const char* pConvertedFrom, size_t nFrom, + char* pConvertedTo, size_t nTo ) + { + cDebug d("tss_ReverseConvert< B, S, C >()"); + d.TraceDebug( "Converted from: %s\n", util_output_bytes( (void*)pConvertedFrom, nFrom ).c_str() ); + d.TraceDebug( "Converted to: %s\n", util_output_bytes( (void*)pConvertedTo, nTo ).c_str() ); + + char aBuffer[ MB_LEN_MAX ]; +#ifdef _DEBUG + for( size_t foo = 0; foo < sizeof( aBuffer ); foo++ ) + aBuffer[ foo ] = 0xCD; +#endif + char* pBuf = &aBuffer[0]; + size_t nBuf = sizeof( aBuffer ); + + const char* pSrc = pConvertedTo; + size_t nSrc = nTo; + + size_t nConv = // NOTE: + iconv( revConv, // On return, these addresses + (ICONV_SOURCE_TYPE**)&pSrc, // are set for one past the last + &nSrc, // "item" converted successfully + &pBuf, + &nBuf ); + + if( nConv == (size_t)-1 ) + { + d.TraceDebug( "reverse conversion failed: iconv error\n" ); + return false; + } + + d.TraceDebug( "sizeof( aBuffer ): %u, nBuf: %u, nFrom: %u\n", sizeof( aBuffer ), nBuf, nFrom ); + d.TraceDebug( "reverse conversion got: %s\n", util_output_bytes( (void*)&aBuffer[0], sizeof( aBuffer ) - nBuf ).c_str() ); + + if( ( ( sizeof( aBuffer ) - nBuf ) != nFrom ) || // convertedFrom and check must be same size + ( 0 != memcmp( pConvertedFrom, &aBuffer[0], nFrom ) ) ) // must be same value, too + { + d.TraceDebug( "reverse conversion failed: converted to a different value\n" ); + return false; + } + + return true; + } + + template< class CharT > + bool tss_IsFlaggedCharacter( CharT ch ) + { + return false; + } + + template<> + bool tss_IsFlaggedCharacter< dbchar_t >( dbchar_t wch ) + { + return cConvertUtil::ValueInReservedRange( wch ); + } + + template< class BufferT, class SourceT > + int + tss_ConvertOneCharacter( iconv_t convForward, + iconv_t convReverse, + const char** ppSource, size_t* pnSourceLeft, + char** ppBuffer, size_t* pnBufferLeft +#if ( ! SUPPORTS_EXPLICIT_TEMPLATE_FUNC_INST ) + , BufferT /*dummy*/, SourceT /*dummy*/ +#endif + ) + { + cDebug d("tss_ConvertOneCharacter< B, S, C >()"); + + const char* pSrc = *ppSource; + char* pBuf = *ppBuffer; + + //-- HACK!!!! BAM -- see if it is one of our reserved UCS2 characters + // TODO:BAM -- how does this affect our converters that don't use the UTF-8 step? + if( tss_IsFlaggedCharacter( **( (SourceT**)ppSource ) ) ) + { + d.TraceDebug( "Found one of our unconvertable characters in the reserved range!\n" ); + return -1; + } + + //-- Try to find the number of items needed to get a complete character + size_t nSrcTry; + for( nSrcTry = sizeof( SourceT ); + nSrcTry <= *pnBufferLeft && nSrcTry <= MB_LEN_MAX; + nSrcTry += sizeof( SourceT ) ) + { + size_t nSrcLeft = nSrcTry; + size_t nBufLeft = *pnBufferLeft;// Try to find a character in 'n' items + + // NOTE: On solaris sparc, iconv will attempt to NULL terminate the output, + // so make sure that the buffer has space for a terminating NULL + d.TraceDebug( "attempting to convert with %u items\n", nSrcTry ); + size_t nConv = // NOTE: + iconv( convForward, // On return, these addresses + (ICONV_SOURCE_TYPE**)&pSrc, // are set for one past the last + &nSrcLeft, // "item" converted successfully + &pBuf, + &nBufLeft ); + + if( nConv == (size_t)-1 ) + { + if( errno == EINVAL ) + { + d.TraceDebug( "more items needed\n" ); + continue; + } + else + { + d.TraceDebug( "iconv failed with %d (not EINVAL)\n", errno ); + return -1; + } + } + else + { + if( tss_ReverseConvert( + convReverse, + *ppSource, + pSrc - *ppSource, + *ppBuffer, + pBuf - *ppBuffer ) ) + { + // Modify source items to return + + ASSERT( nSrcLeft == 0 ); + + *ppSource = pSrc; + *ppBuffer = pBuf; + *pnSourceLeft -= nSrcTry; + *pnBufferLeft = nBufLeft; + + return nConv; + } + else + { + d.TraceDebug( "reverse conversion failed\n" ); + return -1; + } + } + } + + //-- No valid character found in nBufferLeft or MB_LEN_MAX items + d.TraceDebug( "no valid character found after %u items.\n", nSrcTry - 1 ); + return -1; + } + + + // NOTE: is number of T's (as opposed to the number of Characters + // or Bytes) So for a NTWCS sequence, Item is the number of Characters + // while for a NTMBS sequence, Item is the number of char's (Bytes). + // The low-down is that n????Items represents the "Count of T's" + + // NOTE: pBuffer should really have (nBufferItems+1) buffer items, because some + // platforms use the last character to NULL terminate. + template< class BufferT, class SourceT, class ConvT > + int + tss_Converter( iconv_t convForward, + iconv_t convReverse, + BufferT* pBuffer, size_t nBufferItems, + const SourceT* pSource, size_t nSourceItems, + ConvT& ConvertByte ) + { + cDebug d( "tss_Converter< BufferT, SourceT >()" ); + +#ifdef _DEBUG + for( size_t s = nBufferItems; s; s-- ) + pBuffer[s] = 0xCD; + d.TraceDebug( "sizeof buffer: %d, sizeof source: %d\n", sizeof( BufferT ), sizeof( SourceT ) ); + d.TraceDebug( "buffer size: %d, source size: %d\n", nBufferItems, nSourceItems ); + d.TraceDebug( "source: %s\n", util_output_bytes( (void*)pSource, nSourceItems*sizeof( SourceT ) ).c_str() ); +#endif + +#ifndef HACK_FOR_SOLARIS // See NOTE above + nBufferItems++; +#endif + //--Get BYTES to process for in and out sequences + size_t nBufferLeft = nBufferItems * sizeof(BufferT); + size_t nSourceLeft = nSourceItems * sizeof(SourceT); + + //--Setup BYTE iterators to in and out sequences + + BufferT* pBuf = pBuffer; + const SourceT* pSrc = pSource; + + + //--Start Iterative Conversion + + while ( nSourceLeft > 0 ) + { + // Convert as much of the sequence as we can. + + // NOTE: On solaris sparc, iconv will attempt to NULL terminate the output, + // so make sure that the buffer has space for a terminating NULL + size_t nConv = // NOTE: +#if SUPPORTS_EXPLICIT_TEMPLATE_FUNC_INST + tss_ConvertOneCharacter( +#else + tss_ConvertOneCharacter( +#endif + convForward, + convReverse, // On return, these addresses + (const char**)&pSrc, // are set for one past the last + &nSourceLeft, // "item" converted successfully + (char**)&pBuf, + &nBufferLeft +#if ( ! SUPPORTS_EXPLICIT_TEMPLATE_FUNC_INST ) + , BufferT(), SourceT() +#endif + ); + + if ( nConv == (size_t)-1 ) // Indidates Conversion Error! + { + if ( nBufferLeft <= 0 ) + { + d.TraceDebug( "No buffer space left\n" ); + return 0; + } + // TODO:BAM -- handle other iconv errors! + + //--Must attempt Manual Conversion. + ASSERT( (size_t)pSrc % sizeof( SourceT ) == 0 ); + ASSERT( (size_t)pBuf % sizeof( BufferT ) == 0 ); + + d.TraceDebug( "conversion failed: %s\n", strerror( errno ) ); + d.TraceDebug( "manually converting %X...\n", tss::util::char_to_size( *pSrc ) ); + + //-- Convert characters and reposition counters and pointers + if( ! ConvertByte.Convert( &pBuf, &nBufferLeft, &pSrc, &nSourceLeft ) ) + return 0; + } + } + + d.TraceDebug( "buffer out: %s\n", util_output_bytes( (void*)pBuffer, nBufferItems * sizeof(BufferT) - nBufferLeft ).c_str() ); + return nBufferItems - (nBufferLeft / sizeof(BufferT)); + } + +}//Unique + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cIconvConverter +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +cIconvConverter::cIconvConverter() +{ + Init(); +} + +cIconvConverter::~cIconvConverter() +{ + // close conversion handles + cIconvUtil::CloseHandle( icFromDb ); + cIconvUtil::CloseHandle( icToDb ); +} + +/* static */ +bool cIconvConverter::Test() +{ + bool testResult = true; + cDebug d( "cCodeConverter::Test()" ); + + // + // try to get the current code page id + // + const char* pCP = NULL; + if( ! cIconvUtil::GetCodePageID( &pCP ) ) + { + d.TraceDebug( "No code page.\n" ); + return false; + } + d.TraceDebug( "Got code page %s.\n", pCP ); + + + // + // find if converters are available + // + testResult &= cIconvUtil::TestConverter( pCP, cIconvUtil::GetIconvDbIdentifier() ); + testResult &= cIconvUtil::TestConverter( cIconvUtil::GetIconvDbIdentifier(), pCP ); + return testResult; +} + + +void cIconvConverter::Init() +{ + // NOTE:BAM -- if the platform doesn't have a XXX to UCS2 conversion, + // you can make one with the genxlt command.... + icToDb = cIconvUtil::OpenHandle( cIconvUtil::GetIconvDbIdentifier(), cIconvUtil::GetCodePageID() ); + icFromDb = cIconvUtil::OpenHandle( cIconvUtil::GetCodePageID(), cIconvUtil::GetIconvDbIdentifier() ); +} + +int +cIconvConverter::Convert( + ntmbs_t pbz, size_t nBytes, + const_ntdbs_t pwz, size_t nChars ) +{ + cDebug d("cIconvConverter::Convert( ntdbs_t -> ntmbs_t )"); + + if ( pbz == 0 || ( pwz == 0 && nChars ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + // + // reset converter + // + cIconvUtil::ResetConverter( icFromDb ); + + // + // do conversion + // + + ByteConvert< mbchar_t, dbchar_t > bc; + int nConverted = tss_Converter( icFromDb, icToDb, pbz, nBytes, pwz, nChars, bc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted < nBytes ); + + return nConverted; +} + +int +cIconvConverter::Convert( + ntdbs_t pwz, size_t nch, + const_ntmbs_t pbz, size_t nBytes ) +{ + cDebug d("cIconvConverter::Convert( ntmbs to ntdbs )"); + + if ( pwz == 0 || ( pbz == 0 && nBytes ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + // + // reset converter + // + cIconvUtil::ResetConverter( icToDb ); + + // + // do conversion + // + ByteConvert< dbchar_t, mbchar_t > bc; + int nConverted = tss_Converter( icToDb, icFromDb, pwz, nch, pbz, nBytes, bc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted <= nch ); + + return nConverted; +} + + + + + + + + + +/* + + +//-- Converts one SourceT char to one BufferT char +// checks to see that no OS-implementation-defined +// conversion took place... +template< class BufferT, class SourceT > +int +tss_Convert( iconv_t dbConv, + BufferT* pBuffer, size_t nBufferItems, + const SourceT* pSource, size_t nSourceItems ) +{ + // + // Perform first conversion + // + + //-- Get BYTES to process for in and out sequences + size_t nBufferLeft1 = nBufferItems * sizeof(BufferT); + size_t nSourceLeft1 = nSourceItems * sizeof(SourceT); + + //-- Set up BYTE iterators to in and out sequences + char* pBuf1 = (char*)( pBuffer + 0 ); + char* pSrc1 = (char*)( pSource + 0 ); + + //-- NOTE: On solaris sparc, iconv will attempt to NULL terminate the output, + // so make sure that the buffer has space for a terminating NULL + size_t nConv1 = // NOTE: + ::iconv( dbConv, // On return, these addresses + (ICONV_SOURCE_TYPE*) &pSrc1, // are set for one past the last + &nSourceLeft1, // "item" converted successfully + &pBuf1, + &nBufferLeft1 ); + + //-- Did conversion succeed? + if( nConv1 != 1 ) + { + d.tracedebug(); + return 0; + } + size_t nSrcBytesUsed1 = pSrc1 - (char*)pSource; + size_t nBufBytesUsed1 = pBuf1 - (char*)pBuffer; + + // + // Make sure no implementation-defined conversion occured + // So see that the reverse conversion works out to the same source char + // + + //-- Get BYTES to process for in and out sequences + SourceT secondBuf[ MB_LEN_MAX ]; + size_t nBufferLeft2 = MB_LEN_MAX * sizeof( SourceT ); + size_t nSourceLeft2 = ((Buffer*)pBuf) - pBuffer; + + //-- Set up BYTE iterators to in and out sequences + char* pBuf2 = (char*)&secondBuf[0]; + char* pSrc2 = (char*)pBuffer; + size_t nConv2 = + ::iconv( mbConv, // On return, these addresses + (ICONV_SOURCE_TYPE*) &pSrc2, // are set for one past the last + &nSourceLeft2, // "item" converted successfully + &pBuf2, + &nBufferLeft2 ); + + //-- Did conversion succeed? + if( nConv2 != 1 ) + { + d.tracedebug(); + return 0; + } + size_t nSrcBytesUsed2 = pSrc2 - (char*)&secondBuf[0]; + if( ( nSrcBytesUsed1 != nSrcBytesUsed2 ) || + ( 0 != memcmp( &secondBuf[0], pBuffer, nSrcBytesUsed1 ) ) ) + { + d.tracedebug(); + return 0; + } + + return( nSrcBytesUsed1 and nBufBytesUsed1 ); +} +*/ + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cDoubleIconvConverter +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +cDoubleIconvConverter::cDoubleIconvConverter() +{ + Init(); +} + +cDoubleIconvConverter::~cDoubleIconvConverter() +{ + // close conversion handles + cIconvUtil::CloseHandle( icMbToUTF8 ); + cIconvUtil::CloseHandle( icUTF8ToDb ); + cIconvUtil::CloseHandle( icDbToUTF8 ); + cIconvUtil::CloseHandle( icUTF8ToMb ); +} + +/* static */ +bool cDoubleIconvConverter::Test() +{ + bool testResult = true; + cDebug d( "cDoubleIconvConverter::Test()" ); + + // + // try to get the current code page id + // + const char* pCP = NULL; + if( ! cIconvUtil::GetCodePageID( &pCP ) ) + { + d.TraceDebug( "No code page.\n" ); + return false; + } + ASSERT( pCP && *pCP ); + d.TraceDebug( "Got code page %s.\n", pCP ); + + + // + // find if converters are available + // + testResult &= cIconvUtil::TestConverter( cIconvUtil::GetMiddleIdentifier(), pCP ); + testResult &= cIconvUtil::TestConverter( cIconvUtil::GetIconvDbIdentifier(), cIconvUtil::GetMiddleIdentifier() ); + testResult &= cIconvUtil::TestConverter( cIconvUtil::GetMiddleIdentifier(), cIconvUtil::GetIconvDbIdentifier() ); + testResult &= cIconvUtil::TestConverter( pCP, cIconvUtil::GetMiddleIdentifier() ); + + return testResult; +} + + +void cDoubleIconvConverter::Init() +{ + icMbToUTF8 = cIconvUtil::OpenHandle( cIconvUtil::GetMiddleIdentifier(), cIconvUtil::GetCodePageID() ); + icUTF8ToDb = cIconvUtil::OpenHandle( cIconvUtil::GetIconvDbIdentifier(), cIconvUtil::GetMiddleIdentifier() ); + icDbToUTF8 = cIconvUtil::OpenHandle( cIconvUtil::GetMiddleIdentifier(), cIconvUtil::GetIconvDbIdentifier() ); + icUTF8ToMb = cIconvUtil::OpenHandle( cIconvUtil::GetCodePageID(), cIconvUtil::GetMiddleIdentifier() ); +} + +int +cDoubleIconvConverter::Convert( + ntmbs_t pbz, size_t nBytes, + const_ntdbs_t pwz, size_t nChars ) +{ + cDebug d("cDoubleIconvConverter::Convert( ntdbs_t -> ntmbs_t )"); + + // + // initial checking + // + if ( pbz == 0 || ( pwz == 0 && nChars ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + ////////////////////////////////////////////////// + // do conversion to UTF8 + ////////////////////////////////////////////////// + // + // reset first converter + // + cIconvUtil::ResetConverter( icDbToUTF8 ); + + // + // create middle buffer + // + size_t nBufBytes = nChars * MB_LEN_MAX; + ntmbs_t pszBuffer = (ntmbs_t)::operator new( nBufBytes + 1 ); + std::auto_ptr pBuf( pszBuffer ); + + // + // do first conversion + // + std::list lb; // buffer for invalid bytes + ToUTF8Convert< mbchar_t, dbchar_t > tc( lb ); + int nConverted = tss_Converter( icDbToUTF8, icUTF8ToDb, pszBuffer, nBufBytes, pwz, nChars, tc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted <= nBufBytes ); + + ////////////////////////////////////////////////// + // do conversion to MB char + ////////////////////////////////////////////////// + // + // reset second converter + // + cIconvUtil::ResetConverter( icUTF8ToMb ); + + // + // do second conversion + // + FromUTF8Convert< mbchar_t, mbchar_t > fc( lb ); + nConverted = tss_Converter( icUTF8ToMb, icMbToUTF8, pbz, nBytes, pszBuffer, nConverted, fc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted <= nBytes ); + + // + // return number of bytes converted + // + return nConverted; +} + +int +cDoubleIconvConverter::Convert( + ntdbs_t pwz, size_t nch, + const_ntmbs_t pbz, size_t nBytes ) +{ + cDebug d("cDoubleIconvConverter::Convert( ntmbs to ntdbs )"); + + if ( pwz == 0 || ( pbz == 0 && nBytes ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + ////////////////////////////////////////////////// + // do conversion to UTF-8 char + ////////////////////////////////////////////////// + // + // reset first converter + // + cIconvUtil::ResetConverter( icMbToUTF8 ); + + // + // create middle buffer + // + size_t nBufBytes = nBytes * MB_LEN_MAX; + ntmbs_t pszBuffer = (ntmbs_t)::operator new( nBufBytes + 1 ); + std::auto_ptr pBuf( pszBuffer ); + + // + // do first conversion + // + std::list lb; // buffer for invalid bytes + ToUTF8Convert< mbchar_t, mbchar_t > tc( lb ); + int nConverted = tss_Converter( icMbToUTF8, icUTF8ToMb, pszBuffer, nBufBytes, pbz, nBytes, tc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted <= nBufBytes ); + + ////////////////////////////////////////////////// + // do conversion to DB char + ////////////////////////////////////////////////// + // + // reset second converter + // + cIconvUtil::ResetConverter( icUTF8ToDb ); + + // + // do second conversion + // + FromUTF8Convert< dbchar_t, mbchar_t > fc( lb ); + nConverted = tss_Converter( icUTF8ToDb, icDbToUTF8, pwz, nch, pszBuffer, nConverted, fc ); + if ( !nConverted ) + return tss_dispatch_errno( d ); + ASSERT( nConverted <= nch ); + + return nConverted; +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cIconvUtil +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/* static */ +iconv_t cIconvUtil::OpenHandle( const char* pTo, const char* pFrom ) +{ + cDebug d("cIconvUtil::OpenHandle"); + iconv_t ic; + + ic = iconv_open( pTo, pFrom ); + if( ic == (iconv_t)-1 ) + throw eConverterUnsupportedConversion(); + + d.TraceDebug( "opened %s to %s conversion\n", pFrom, pTo ); + return ic; +} + +/* static */ +bool cIconvUtil::GetCodePageID( const char** ppCP ) +{ + *ppCP = nl_langinfo( CODESET ); + + return( *ppCP && **ppCP ); +} + +/* static */ +const char* cIconvUtil::GetCodePageID() +{ + const char* pCurCodePage; + + if( ! GetCodePageID( &pCurCodePage ) ) + throw eConverterUnknownCodepage(); + + return pCurCodePage; +} + +/* static */ +const char* cIconvUtil::GetIconvDbIdentifier() +{ + ASSERT( false ); + throw eConverterUnknownCodepage(); + return NULL; +} + +/* static */ +const char* cIconvUtil::GetMiddleIdentifier() +{ + return "UTF-8"; +} + + +/* static */ +void cIconvUtil::ResetConverter( iconv_t ic ) +{ + char* p = 0; + size_t s = 0; + + size_t i = iconv( ic, + (ICONV_SOURCE_TYPE**) &p, + &s, &p, &s ); + if ( i == (size_t)-1 ) + { + ASSERT( false ); + throw eConverterReset(); + } +} + +/* static */ +void cIconvUtil::CloseHandle( iconv_t ic ) +{ + int ret = iconv_close( ic ); + ASSERT( ret != -1 ); +} + +/* static */ +bool cIconvUtil::TestConverter( const char* pTo, const char* pFrom ) +{ + cDebug d( "cIconvUtil::TestConverter()" ); + + iconv_t i = iconv_open( pTo, pFrom ); + if( (iconv_t)-1 == i ) + { + d.TraceDebug( "No %s to %s conversion.\n", pFrom, pTo ); + tss_dispatch_iconvopen_error(); + return false; + } + else + { + d.TraceDebug( "Valid conversion for %s to %s.\n", pFrom, pTo ); + cIconvUtil::CloseHandle( i ); + return true; + } +} + +#endif//TSS_USE_ICONV_CCONV16 + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cWcharIs32BitUcs2Converterer +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +namespace /*Unique*/ +{ + //-- Ensures 1-to-1 mb to wide character mapping by doing a reverse conversion + // and comparing the results + int + tss_mbtowc( wchar_t* pwch, const mbchar_t* pch, size_t nBytes ) + { + // convert forward + int nNarrow = ::mbtowc( pwch, pch, nBytes ); + if( nNarrow == -1 ) + return -1; + + // convert backwards + mbchar_t ach[ MB_LEN_MAX ]; + int nWide = ::wctomb( ach, *pwch ); + if( nWide == -1 ) + return -1; + + // compare... + if( ( nNarrow > (int)nBytes ) || + ( 0 != memcmp( ach, pch, nNarrow ) ) ) + return -1; + + // success! + return nNarrow; + } + + //-- Ensures 1-to-1 mb to wide character mapping by doing a reverse conversion + // and comparing the results + int + tss_wctomb( mbchar_t* pch, wchar_t wch ) + { + // convert forward + int nWide = ::wctomb( pch, wch ); + if( nWide == -1 ) + return -1; + + // convert backwards + wchar_t wchTest; + int nNarrow = ::mbtowc( &wchTest, pch, MB_CUR_MAX ); + if( nNarrow == -1 ) + return -1; + + // compare... + if( wchTest != wch ) + return -1; + + // success! + return nWide; + } + + int + tss_wcstombs( ntmbs_t pbz, const_ntwcs_t pwz, size_t nCount ) + { + cDebug d("tss_wcstombs"); + + size_t nConv; + size_t N; + for ( nConv = 0, N = 0; *pwz; ++pwz, pbz += N, ++nConv ) + { + N = tss_wctomb( pbz, *pwz ); + if ( N == (size_t)-1 ) + { + *pbz = cConvertUtil::ConvertNonChar( (dbchar_t)*pwz ); + N = 1; + } + } + + return (int)nConv; + } + + + int + tss_mbstowcs( ntwcs_t pwz, const_ntmbs_t pbz, size_t nBytes ) + { + cDebug d("tss_mbstowcs"); + + size_t N; + size_t nConv; + const_ntmbs_t end = &pbz[nBytes]; + for ( nConv = 0, N = 0; *pbz; pbz += N, ++pwz, ++nConv ) + { + N = tss_mbtowc( pwz, pbz, end - pbz ); + if ( N == (size_t)-1 ) + { + d.TraceDebug( + "manually converting %X...\n", + cConvertUtil::ConvertNonChar( *pbz ) ); + + *pwz = (wchar_t)cConvertUtil::ConvertNonChar( *pbz ); + N = 1; + } + } + + return (int)nConv; + } +}//Unique + +#if WCHAR_IS_32_BITS + +int +cWcharIs32BitUcs2Converterer::Convert( + ntmbs_t pbz, size_t nBytes, + const_ntdbs_t pwz, size_t nCount ) +{ + if ( pbz == 0 || ( pwz == 0 && nCount ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + // cast our dbchar_t to wchar_t's first + ntwcs_t pwzBuffer = new wchar_t[ nCount + 1 ]; + for( size_t n = 0; n < nCount; n++ ) + pwzBuffer[n] = pwz[n]; + pwzBuffer[nCount] = 0x00; // null terminate + + int nConv = tss_wcstombs( pbz, pwzBuffer, nBytes ); + if ( (size_t)nConv == (size_t)-1 ) + { + cDebug d("cWcharIs32BitUcs2Converterer::Convert( ntdbs to ntmbs )"); + char* psz = new char[ nCount * 2 ]; + char* at = psz; + while ( *pwzBuffer ) + *at++ = *pwzBuffer++; + *at = 0x00; + d.TraceDebug( "Invalid Input: [%s]\n", psz ); + d.TraceDebug( "%s\n", util_output_bytes( (void*)pwz, nCount*sizeof(wchar_t)).c_str() ); + + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + return nConv; +} + +int +cWcharIs32BitUcs2Converterer::Convert( + ntdbs_t pwz, size_t nCount, + const_ntmbs_t pbz, size_t nBytes ) +{ + cDebug d("cWcharIs32BitUcs2Converterer::Convert( ntmbs to ntdbs )"); + + // Validate Input + if ( pwz == 0 || ( pbz == 0 && nBytes ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + // mb to wc to a buffer of wide chars then.... + wchar_t* pwzBuffer = new wchar_t[ nCount ]; + + int nConv = tss_mbstowcs( pwzBuffer, pbz, nCount ); + if ( nConv == -1 ) + { + d.TraceDebug( "Invalid Input: [%s]\n", pbz ); + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + // ...cast those chars to dbchar_ts + for( size_t at = 0; at < (size_t)nConv; ++at, ++pwzBuffer ) + { + wchar_t wch = *pwzBuffer; + if ( wch > 0xFFFF ) + { + d.TraceDebug("found wchar_T > 0xFFFF: %X\n", wch ); + throw eConverterFatal( _T("Cannot truncate wchar_t to dbchar_t") ); + } + + pwz[ at ] = (dbchar_t)wch; + } + pwz[nConv] = 0x00; + + return nConv; +} + + +#endif // WCHAR_IS_32_BITS + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cWcharIs16BitUcs2Converterer +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#if WCHAR_IS_16_BITS + +int +cWcharIs16BitUcs2Converterer::Convert( + ntmbs_t pbz, size_t nbMB, + const_ntdbs_t pwz, size_t nch ) +{ + // Validate Input + if ( pbz == 0 || ( pwz == 0 && nch ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + int nConverted = tss_wcstombs( pbz, pwz, nbMB ); + if ( nConverted == -1 ) + { + cDebug d("cWcharIs16BitUcs2Converterer[ntdbs->ntmbs]"); + ntmbs_t psz = new char[ nch * 2 ]; + ntmbs_t at = psz; + while ( *pwz ) + *at++ = (mbchar_t)*pwz++; + *at = 0x00; + d.TraceDebug( "Invalid Input: [%s]\n", psz ); + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + return nConverted; +} + +int +cWcharIs16BitUcs2Converterer::Convert( + ntdbs_t pwz, size_t nch, + const_ntmbs_t pbz, size_t nBytes ) +{ + // Validate Input + if ( pbz == 0 || ( pwz == 0 && nch ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + int nConverted = tss_mbstowcs( pwz, pbz, nch ); + if ( nConverted == -1 ) + { + cDebug d("cWcharIs16BitUcs2Converterer::Convert( ntmbs to ntdbs )"); + d.TraceDebug( "Invalid Input: [%s]\n", pbz ); + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + return nConverted; +} + +#endif // WCHAR_IS_16_BITS + + + +int +cGoodEnoughConverterer::Convert( + ntmbs_t pbz, size_t nBytes, + const_ntdbs_t pwz, size_t nCount ) +{ + if ( pbz == 0 || ( pwz == 0 && nCount ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + char* at = pbz; + const dbchar_t* dat = pwz; + while ( *dat ) + { + if( *dat > 0xFF ) + { + *at = cConvertUtil::ConvertNonChar( *dat ); + } + else + { + *at = (char)*dat; + } + + at++; + dat++; + } + + *at = 0x00; + + return( (size_t)at - (size_t)pbz ); +} + +int +cGoodEnoughConverterer::Convert( + ntdbs_t pwz, size_t nCount, + const_ntmbs_t pbz, size_t nBytes ) +{ + // Validate Input + if ( pwz == 0 || ( pbz == 0 && nBytes ) ) + throw eConverterFatal( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + const char* at = pbz; + dbchar_t* dat = pwz; + while ( *at ) + { + if( (unsigned char)*at > (unsigned char)0x7Fu ) + { + *dat = cConvertUtil::ConvertNonChar( *at ); + } + else + { + *dat = (uint16)(unsigned char)*at; + } + + dat++; + at++; + } + + *dat = 0x0000; + + return( ( (size_t)dat - (size_t)pwz ) / sizeof( dbchar_t ) ); +} + +dbchar_t cConvertUtil::ConvertNonChar( mbchar_t ch ) +{ + cDebug d("cConvertUtil::ConvertNonChar( mbchar_t to dbchar_t )"); + + if( ! ValueInReservedRange( ch ) ) + { + d.TraceDebug( "Invalid Input: [%X]\n", ch ); + throw eConverterFatal( _T("mbchar_t is not high ascii!") ); + } + + dbchar_t wch = (dbchar_t)( tss::util::char_to_size( ch ) + TSS_UCS2_RESERVED_START ); + + d.TraceDebug( "Converted 0x%08X to 0x%08X\n", + tss::util::char_to_size( ch ), + tss::util::char_to_size( wch ) ); + + return( wch ); +} + +mbchar_t cConvertUtil::ConvertNonChar( dbchar_t wch ) +{ + cDebug d("cConvertUtil::ConvertNonChar( dbchar_t to mbchar_t )"); + + if( ! ValueInReservedRange( wch ) ) + { + d.TraceDebug( "Invalid Input: [%X]\n", wch ); + throw eConverterFatal( _T("Cannot truncate dbchar_t to mbchar_t") ); + } + + mbchar_t ch = (mbchar_t)( wch - TSS_UCS2_RESERVED_START ); + + d.TraceDebug( "Converted 0x%08X to 0x%08X\n", + tss::util::char_to_size( wch ), + tss::util::char_to_size( ch ) ); + + return( ch ); +} + +bool cConvertUtil::ValueInReservedRange( dbchar_t wch ) +{ + size_t s = tss::util::char_to_size( wch ); + return( ( s >= TSS_UCS2_RESERVED_START ) && + ( s <= TSS_UCS2_RESERVED_END ) ); +} + +bool cConvertUtil::ValueInReservedRange( mbchar_t ch ) +{ + size_t s = tss::util::char_to_size( ch ); + return( ( s >= TSS_HIGH_ASCII_START ) && + ( s <= TSS_HIGH_ASCII_END ) ); +} diff --git a/src/core/codeconvert.h b/src/core/codeconvert.h new file mode 100644 index 0000000..1829fd0 --- /dev/null +++ b/src/core/codeconvert.h @@ -0,0 +1,275 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: codeconvert.h +// Date....: 9/2/99 +// Creator.: Brian McFeely (bmcfeely) +// +// CodePage Conversion between Character Sequences +// +// Notes on Terminology +// -------------------- +// ntbs_t -- A null-terminated single byte sequence (pointer) +// char -- A single character +// +// ntmbs_t -- A null-terminated multibyte sequence (pointer) +// mbchar_t -- A single lead or trail byte +// +// ntdbs_t -- A null-terminated two-byte character sequence (pointer) +// dbchar_t -- A single double-byte character +// +// ntwcs_t -- null-terminated two or four-byte wide character sequence (pointer) +// wchar_t -- A single wide (double or quad) character +// +// This module happens to use only multibyte (ntmbs) and double-byte only +// (ntwcs). None of these routines should be used with a wide character +// of unknown size, such as wchar_t, or a UCS4 or quad-byte (ntqbs) pointer. +// + +#ifndef __CODECONVERT_H +#define __CODECONVERT_H + +/// Requirements + +#include "platform.h" // for: Platform specific code +#include "ntmbs.h" // for: NTBS, NTMBS, NTWCS, and NTDBS types + + +/// Exceptions + +TSS_EXCEPTION( eConverter, eError ); +TSS_EXCEPTION( eConverterReset, eConverter ); +TSS_EXCEPTION( eConverterFatal, eConverter ); +TSS_EXCEPTION( eConverterUnsupportedConversion, eConverter ); +TSS_EXCEPTION( eConverterUnknownCodepage, eConverter ); + + +/// Classes + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +* iCodeConverter -- The CodePage Converter Interface +* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +* SYNOPSIS: Converts between the local code page and UCS2 (if possible) +* Ensures a one-to-one correspondance between mb and UCS2 by +* making sure the mapping is roundtrip. If it is not roundtrip, +* or a byte value is not a character, it is cast to a reserved +* region of UCS2 ( 0xE000 - 0xE0FF ). +* CONSTRAINTS: +* +* INVARIANTS: +* +*/ +class iCodeConverter +{ + public: + + static iCodeConverter* GetInstance(); // Singleton + + + /// Subclass Responsibilities + virtual + int + Convert( + ntmbs_t, // NTMBS buffer + size_t, // Capacity in mbchar_t's (bytes) + const_ntdbs_t, // null terminated two-byte wide character (UCS2 rep) + size_t nCount ) = 0; // Amount to convert in dbchar_t's + // returns number of buffer items converted, -1 on error + + + virtual + int + Convert( + ntdbs_t, // NTDBS (Null-terminated two byte sequence) buf + size_t, // Capacity in dbchar_t's + const_ntmbs_t, // Null-terminated multi-byte sequence + size_t ) = 0; // Capacity in mbchar_t's (bytes) + // returns number of buffer items converted, -1 on error + + protected: + + iCodeConverter() + { + }; + + private: + + static iCodeConverter* CreateConverter(); + static iCodeConverter* CreateGoodEnoughConverter(); + + static iCodeConverter* m_pInst; + +}; + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cIconvConverter -- Concrete Converter +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HAVE_ICONV_H +#include + +#ifdef HAVE_LANGINFO_H +#ifndef __USE_XOPEN +#define __USE_XOPEN 1 +#endif +#include +#endif + +class cIconvUtil +{ + public: + + static const char* GetCodePageID(); // gets code page id for current locale, throws if error + static bool GetCodePageID( const char** ppCP ); + static const char* GetIconvDbIdentifier(); + static const char* GetMiddleIdentifier(); + static void ResetConverter( iconv_t ); + static bool TestConverter( const char* pTo, const char* pFrom ); + static iconv_t OpenHandle( const char* pTo, const char* pFrom ); // throws + static void CloseHandle( iconv_t ic ); +}; + + +class cIconvConverter : public iCodeConverter +{ + public: + + static bool Test(); // is there a conversion for the current codepage? + + virtual int Convert( ntmbs_t, size_t, const_ntdbs_t, size_t ); + virtual int Convert( ntdbs_t, size_t, const_ntmbs_t, size_t ); + + cIconvConverter(); + ~cIconvConverter(); + + private: + void Init(); + + iconv_t icToDb; + iconv_t icFromDb; +}; + +class cDoubleIconvConverter : public iCodeConverter +{ + public: + + static bool Test(); // is there a conversion for the current codepage? + + virtual int Convert( ntmbs_t, size_t, const_ntdbs_t, size_t ); + virtual int Convert( ntdbs_t, size_t, const_ntmbs_t, size_t ); + + cDoubleIconvConverter(); + ~cDoubleIconvConverter(); + + private: + + void Init(); + + iconv_t icMbToUTF8; + iconv_t icUTF8ToDb; + + iconv_t icDbToUTF8; + iconv_t icUTF8ToMb; +}; + +#endif // HAVE_ICONV_H + + +/// QUESTION:RAD -- Why not just have one platform-specific of the below + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cWcharIs32BitUcs2Converterer +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#if WCHAR_IS_32_BITS + +// TODO:BAM -- this is not really correct! Convert will not honor nSource!! +// it looks for the first null char! + +class cWcharIs32BitUcs2Converterer : public iCodeConverter +{ +public: + virtual int Convert( ntmbs_t, size_t, const_ntdbs_t, size_t ); + virtual int Convert( ntdbs_t, size_t, const_ntmbs_t, size_t ); +}; + +#endif // WCHAR_IS_32_BITS + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cWcharIs16BitUcs2Converterer +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#if WCHAR_IS_16_BITS + +// TODO:BAM -- this is not really correct! Convert will not honor nSource!! +// it looks for the first null char! + +class cWcharIs16BitUcs2Converterer : public iCodeConverter +{ +public: + virtual int Convert( ntmbs_t, size_t, const_ntdbs_t, size_t ); + virtual int Convert( ntdbs_t, size_t, const_ntmbs_t, size_t ); +}; + +#endif // WCHAR_IS_16_BITS + +// does a straight cast of each mbchar_t byte to a dbchar_t and back. +// converts mbchars > 0x7F to our reserved space +class cGoodEnoughConverterer : public iCodeConverter +{ +public: + virtual int Convert( ntmbs_t, size_t, const_ntdbs_t, size_t ); + virtual int Convert( ntdbs_t, size_t, const_ntmbs_t, size_t ); +}; + + +class cConvertUtil +{ + enum + { + TSS_UCS2_RESERVED_START = 0xE800u, // E000-E8FF is private use range, but + TSS_UCS2_RESERVED_END = 0xE8FFu, // SJIS and EUC use E000-E757 + TSS_HIGH_ASCII_START = 0x0080u, + TSS_HIGH_ASCII_END = 0x00FFu + }; +public: + static dbchar_t ConvertNonChar( mbchar_t ch ); + static mbchar_t ConvertNonChar( dbchar_t ch ); + + static bool ValueInReservedRange( mbchar_t ch ); + static bool ValueInReservedRange( dbchar_t ch ); +}; + + +#endif //__CODECONVERT_H + diff --git a/src/core/codeconvert_t.cpp b/src/core/codeconvert_t.cpp new file mode 100644 index 0000000..1adf87c --- /dev/null +++ b/src/core/codeconvert_t.cpp @@ -0,0 +1,341 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: codeconvert_t.cpp +// Date....: 9/8/99 +// Creator.: Brian McFeely (bmcfeely) +// +// [Description] + +#include "stdcore.h" +#include "codeconvert.h" +#include "core/wchar16.h" +#include "test/test.h" + +#include + +bool util_IsWideCharSameAsNarrow( char ch ); +bool LowASCIILooksLikeUCS2InWchart(); +void TestMbToDb(); +void TestDbToMb(); + +void TestCodeConverter() +{ + cDebug d("TestCodeConverter()"); + +#if ( !(HAVE_ICONV_H) && WCHAR_REP_IS_UCS2 ) + + // + // check that rep is really UCS2 + // + TEST( LowASCIILooksLikeUCS2InWchart() ); +#endif + + d.TraceDetail("Testing multi byte to double byte conversion.\n"); + TestMbToDb(); + d.TraceDetail("TestMbToDb() done.\n"); + +// Took out this test as it currently throws and exception. +// We expect not to be able to convert every UCS2 to a multi-byte char. +// d.TraceDetail("Testing double byte to multi byte conversion.\n"); +// TestDbToMb(); +} + +// first last identify the lhs string +// x identifies the start of the second string +// start identifies the original start of the lhs string +template< class IterT > +bool Compare( IterT first, IterT last, IterT x, IterT start ) +{ + std::pair< IterT, IterT > + p = std::mismatch( first, + last, + x ); + + if( p.first != last ) + { + // success !! + std::cout << "*** mismatched value at: " + << (int)(p.first - start) + << ". Values are: " + << (size_t)tss::util::char_to_size(*p.first) + << " and " + << (size_t)tss::util::char_to_size(*p.second) + << std::endl; + + return Compare( p.first + 1, last, p.second + 1, start ); + } + + return true; +} + +void CompareStrings( const std::string& s1, const std::string& s2 ) +{ + if( s1.length() != s2.length() ) + { + std::cout << "*** string lengths didn't match. Lengths were: " + << s1.length() + << " and " + << s2.length() + << std::endl; + } + + if( Compare( s1.begin(), s1.end(), s2.begin(), s1.begin() ) ) + { + std::cout << "** string matched." + << std::endl; + } +} + + + + +void DisplayString( const std::string& s ) +{ + std::string::size_type i; + for( i = 0; i < s.length(); ++i ) + { + std::cout << std::hex + << std::setw(2) + << std::setfill('0') + << (size_t)(unsigned char) s[i] + << " "; + } +} + +size_t DistanceToOne( size_t n ) +{ + size_t dist; + for( dist = 0; + n != 1; + dist++ ) + { + n = ( n >> 1 ); + } + + ASSERT( n == 1 ); // n was not a power of 2! + + return dist; +} + + +void ConvertAndCompareString( const std::string& s ) +{ + std::cout << "* Converting: "; + DisplayString( s ); + std::cout << std::endl; + + // convert to dbchar_t string + int nWrote; + wc16_string ws; + ws.resize( s.length() ); + nWrote = iCodeConverter::GetInstance()->Convert( (ntdbs_t)ws.c_str(), ws.length(), s.c_str(), ws.length() ); + ASSERT( nWrote != -1 ); + ws.resize( nWrote ); + + // convert back to mbchar_t string + std::string s2; + s2.resize( ws.length() * MB_CUR_MAX ); + nWrote = iCodeConverter::GetInstance()->Convert( (ntmbs_t)s2.c_str(), s2.length(), ws.c_str(), ws.length() ); + ASSERT( nWrote != -1 ); + s2.resize( nWrote ); + + std::cout << "* Result : "; + DisplayString( s2 ); + std::cout << std::endl; + + CompareStrings( s, s2 ); +} + +char NonZeroChar( char ch ) +{ + return ch == 0 ? '0' : ch; +} + +// mbchar_t to dbchar_t +void TestMbToDb() +{ + std::string s; + s.resize( 0x10000 * 2 ); // two bytes for each combination + + for( size_t i = 0; i < 0x1000; i++ ) + { + for( size_t j = 0; j < 0x10; j++ ) + { + size_t first_byte = ( i & 0xFF00 ) >> 8; + ASSERT( first_byte <= 0xFF ); + + size_t second_byte = ( ( i & 0x00F0 ) >> 4 ) | j; + ASSERT( second_byte <= 0xFF ); + + s[ 2 * j ] = NonZeroChar( (char)first_byte ); + s[ ( 2 * j ) + 1 ] = NonZeroChar( (char)second_byte ); + } + + ConvertAndCompareString( s ); + } + + /* + const std::string::size_type TOTAL_VALUE_COMBINATIONS = 0x10000; // 0x100 ^ 2 (256 possible per byte, and two bytes) (must always be this value) + const std::string::size_type CHARS_AT_A_TIME = 0x10; // can change this, but needs to be a power of 2 + const std::string::size_type FIRST_BYTE_MASK = TOTAL_VALUE_COMBINATIONS - CHARS_AT_A_TIME; + const std::string::size_type SECOND_BYTE_MASK = CHARS_AT_A_TIME - 1; + + std::string s; + s.resize( CHARS_AT_A_TIME * 2 ); // two bytes for each combination + + for( size_t i = 0; i < TOTAL_VALUE_COMBINATIONS / CHARS_AT_A_TIME; i++ ) + { + for( size_t j = 0; j < CHARS_AT_A_TIME; j++ ) + { + size_t first_byte = ( ( i & FIRST_BYTE_MASK ) >> DistanceToOne( CHARS_AT_A_TIME ) ); + ASSERT( first_byte <= 0xFF ); + + size_t second_byte = ( ( i & ( SECOND_BYTE_MASK << DistanceToOne( CHARS_AT_A_TIME ) ) | j ); + ASSERT( second_byte <= 0xFF ); + + s[ 2 * j ] = NonZeroChar( (char)first_byte ); + s[ ( 2 * j ) + 1 ] = NonZeroChar( (char)second_byte ); + } + + ConvertAndCompareString( s ); + } + + */ +} + + +// dbchar_t to mbchar_t +void TestDbToMb() +{ + wc16_string ws; + wc16_string::size_type n; + const wc16_string::size_type max = 0x10000; + + // Setup string will all UCS2 characters + ws.resize( max ); + for( n = 1; n < max; n++ ) + { + TEST( n < std::numeric_limits< wc16_string::size_type >::max() ); + ws[ n - 1 ] = (WCHAR16)n; + } + + // convert to mbchar_t string + std::string s; + s.resize((max - 1) * MB_CUR_MAX); + iCodeConverter::GetInstance()->Convert( (ntmbs_t)s.c_str(), s.length(), ws.c_str(), max - 1 ); + + // convert back to dbchar_t string + wc16_string ws2; + ws2.resize(max - 1); + iCodeConverter::GetInstance()->Convert( (ntdbs_t)ws2.c_str(), max - 1, s.c_str(), s.length() ); + + TEST( ws.compare( ws2 ) == 0 ); +} + + +bool util_IsWideCharSameAsNarrow( char ch ) +{ + cDebug d("LowASCIILooksLikeUCS2InWchart()"); + + // + // translate to a wide char + // + wchar_t wc; + int i = mbtowc( &wc, &ch, 1 ); + + // + // assure that it has some representation in + // the wchar character set + // + if( i == -1 ) + { + d.TraceDebug( "mbtowc failed on ch=0x%04X\n", (size_t)(unsigned char)ch ); + return false; + } + + // + // assure that the wide char representation looks like + // UCS2 ( a 8859-1 char in UCS2 looks like 0x00XX, where + // XX is the value of the char ) + // + if( (char)wc != ch ) + { + d.TraceDebug( "comparison failed on ch=0x%04X, wc=0x%04X\n", (size_t)(unsigned char)ch, (size_t)wc ); + return false; + } + + return true; +} + + +bool LowASCIILooksLikeUCS2InWchart() +{ + cDebug d("LowASCIILooksLikeUCS2InWchart()"); + bool fOK = true; + +#if 0 // I hear this function isn't even correct... rjf + + // + // save old locale + // + char* pOldLocale = + strdup( + setlocale( LC_CTYPE, NULL ) ); + d.TraceDebug( "Old locale: %s\n", pOldLocale ); + + // + // set to C locale + // + setlocale( LC_CTYPE, "C" ); + TEST( 0 == strcmp( "C", setlocale( LC_CTYPE, NULL ) ) ); + + // + // check each C locale char ( which is the ISO 8859-1 set ) + // against it's wchar_trepresentation + // + for( char ch = 0x00; fOK && (unsigned char)ch < 0x80U; ch++ ) + fOK &= util_IsWideCharSameAsNarrow( ch ); + + // + // reset locale + // + setlocale( LC_CTYPE, pOldLocale ); + TEST( 0 == strcmp( pOldLocale, setlocale( LC_CTYPE, NULL ) ) ); + free( pOldLocale ); + +#endif + return fOK; +} + +// eof: codeconvert_t.cpp + diff --git a/src/core/core.cpp b/src/core/core.cpp new file mode 100644 index 0000000..536b1ab --- /dev/null +++ b/src/core/core.cpp @@ -0,0 +1,64 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: core.cpp +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdcore.h" +#include "core.h" +#include "coreerrors.h" + +#include "codeconvert.h" // for: iCodeConverter::GetInstance +#include "twlocale.h" // for: cTWLocale::InitGlobalLocale + +TSS_ImplementPackage( cCore ) + +cCore::cCore() +{ + TSS_REGISTER_PKG_ERRORS( core ); + + // NOTE: Initialize code converter when cCore is a dependency + // of another package (created on first call to GetInstance(), + // forcing creation here to hasten the display of any errors) + + cDebug::SetDebugLevel( cDebug::D_DEBUG ); + cDebug::AddOutTarget( cDebug::OUT_STDOUT ); + + cTWLocale::InitGlobalLocale(); + + iCodeConverter::GetInstance(); +} + + +// eof: core.cpp diff --git a/src/core/core.h b/src/core/core.h new file mode 100644 index 0000000..8ec5217 --- /dev/null +++ b/src/core/core.h @@ -0,0 +1,61 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: core.h +// Date....: 05/04/99 +// Creator.: Robert DiFalco (rdifalco) +// +// The Package class for the TSS core library module. +// + +#ifndef __CORE_H +#define __CORE_H + + +//--Requirements + +#include "package.h" // for: Packaging Abstraction + +//--Classes + +TSS_BeginPackage( cCore ) + + TSS_DECLARE_STRINGTABLE; + + public: + + cCore(); + +TSS_EndPackage( cCore ) + +#endif //__CORE_H + diff --git a/src/core/coreerrors.cpp b/src/core/coreerrors.cpp new file mode 100644 index 0000000..5d18642 --- /dev/null +++ b/src/core/coreerrors.cpp @@ -0,0 +1,168 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// coreerrors.cpp +// +// Registers all error strings in the core package +// + +#include "stdcore.h" +#include "coreerrors.h" + +#include "errorgeneral.h" +#include "archive.h" +#include "error.h" +#include "unixexcept.h" +#include "fsservices.h" +#include "serializer.h" +#include "cmdlineparser.h" +#include "twlocale.h" +#include "codeconvert.h" +#include "ntmbs.h" +#include "displayencoder.h" + +TSS_BEGIN_ERROR_REGISTRATION( core ) + +/// Internal + +TSS_REGISTER_ERROR( eInternal(), _T("Internal error.") ) + + +/// General + +TSS_REGISTER_ERROR( eErrorGeneral(), _T("General Error") ); +TSS_REGISTER_ERROR( eOpen(), _T("File could not be opened.") ); +TSS_REGISTER_ERROR( eOpenRead(), _T("File could not be opened for reading.") ); +TSS_REGISTER_ERROR( eOpenWrite(), _T("File could not be opened for writing.") ); +TSS_REGISTER_ERROR( eBadModeSwitch(), _T("Unknown mode specified.") ); +TSS_REGISTER_ERROR( eBadCmdLine(), _T("Command line error.") ); + + +/// Archive + +TSS_REGISTER_ERROR( eArchive(), _T("Archive error.") ) +TSS_REGISTER_ERROR( eArchiveOpen(), _T("File could not be opened.") ) +TSS_REGISTER_ERROR( eArchiveWrite(), _T("File could not be written.") ) +TSS_REGISTER_ERROR( eArchiveRead(), _T("File could not be read.") ) +TSS_REGISTER_ERROR( eArchiveEOF(), _T("End of file reached.") ) +TSS_REGISTER_ERROR( eArchiveSeek(), _T("File seek failed.") ) +TSS_REGISTER_ERROR( eArchiveMemmap(), _T("Memory mapped archive file invalid.") ) +TSS_REGISTER_ERROR( eArchiveOutOfMem(), _T("Archive ran out of memory.") ) +TSS_REGISTER_ERROR( eArchiveInvalidOp(),_T("Archive logic error.") ) +TSS_REGISTER_ERROR( eArchiveFormat(), _T("Archive file format invalid.") ) +TSS_REGISTER_ERROR( eArchiveNotRegularFile(), _T("File is not a regular file.") ) +TSS_REGISTER_ERROR( eArchiveCrypto(), _T("File could not be decrypted.") ) +TSS_REGISTER_ERROR( eArchiveStringTooLong(), _T("String was too long.") ) + + +/// File + +TSS_REGISTER_ERROR( eFile(), _T("File error.") ) +TSS_REGISTER_ERROR( eFileOpen(), _T("File could not be opened.") ) +TSS_REGISTER_ERROR( eFileWrite(), _T("File could not be written.") ) +TSS_REGISTER_ERROR( eFileRead(), _T("File could not be read.") ) +TSS_REGISTER_ERROR( eFileEOF(), _T("End of file reached.") ) +TSS_REGISTER_ERROR( eFileSeek(), _T("File seek failed.") ) +TSS_REGISTER_ERROR( eFileInvalidOp(), _T("File logic error.") ) +TSS_REGISTER_ERROR( eFileTrunc(), _T("File could not be truncated.") ) +TSS_REGISTER_ERROR( eFileClose(), _T("File could not be closed.") ) +TSS_REGISTER_ERROR( eFileFlush(), _T("File could not be flushed.") ) +TSS_REGISTER_ERROR( eFileRewind(), _T("File could not be rewound.") ) + + +/// Win32 + +#if IS_UNIX +TSS_REGISTER_ERROR(eUnix(), _T("Unix API failure.") ) +#endif + +/// FSServices + +TSS_REGISTER_ERROR( eFSServices(), _T("File system error.") ) +TSS_REGISTER_ERROR( eFSServicesGeneric(),_T("File system error.") ) + + +/// Serializer + +TSS_REGISTER_ERROR( eSerializerUnknownType(), _T("Unknown type encountered in file.\nFile format may not be valid for this platform.") ) +TSS_REGISTER_ERROR( eSerializerInputStreamFmt(), _T("Invalid input stream format.") ) +TSS_REGISTER_ERROR( eSerializerOutputStreamFmt(), _T("Invalid output stream format.") ) +TSS_REGISTER_ERROR( eSerializerInputStremTypeArray(), _T("A bad index was encountered in file.") ) +TSS_REGISTER_ERROR( eSerializerArchive(), _T("File read encountered an archive error.") ) +TSS_REGISTER_ERROR( eSerializerVersionMismatch(), _T("File version mismatch.") ) +TSS_REGISTER_ERROR( eSerializerEncryption(), _T("File encryption error.") ) +TSS_REGISTER_ERROR( eSerializer(), _T("File format error.") ) + + +/// Command Line + +TSS_REGISTER_ERROR( eCmdLine(), _T("Command line parsing error.") ) +TSS_REGISTER_ERROR( eCmdLineInvalidArg(), _T("Invalid argument passed on command line.") ) +TSS_REGISTER_ERROR( eCmdLineBadArgParam(), _T("Incorrect number of parameters to a command line argument.") ) +TSS_REGISTER_ERROR( eCmdLineBadParam(), _T("Incorrect number of parameters on command line.") ) +TSS_REGISTER_ERROR( eCmdLineBadSwitchPos(), _T("Switch appears after final command line parameter.") ) +TSS_REGISTER_ERROR( eCmdLineMutEx(), _T("Specified command line switches are mutually exclusive.") ) +TSS_REGISTER_ERROR( eCmdLineDependency(), _T("Command line parameter missing.") ) +TSS_REGISTER_ERROR( eCmdLineMultiArg(), _T("Command line argument specified more than once.") ) + + +/// TWLocale + +TSS_REGISTER_ERROR( eTWLocale(), _T("Localization error.") ) +TSS_REGISTER_ERROR( eTWLocaleBadNumFormat(),_T("Bad number format.") ) + + +/// Character Handling (defined in ntmbs.h) + +TSS_REGISTER_ERROR( eCharacter(), _T("General Character Handling Error.") ) +TSS_REGISTER_ERROR( eCharacterEncoding(), _T("Character Encoding Error.") ) + + +/// Character Conversion Handling (defined in ) + +TSS_REGISTER_ERROR( eConverter(), _T("General conversion error.") ) +TSS_REGISTER_ERROR( eConverterReset(), _T("Converter handle could not be reset.") ) +TSS_REGISTER_ERROR( eConverterFatal(), _T("Catastrophic conversion error.") ) +TSS_REGISTER_ERROR( eConverterUnsupportedConversion(), _T("Unsupported character conversion.") ) +TSS_REGISTER_ERROR( eConverterUnknownCodepage(), _T("Could not identify code page.") ) + +// +// Display Encoder +// + +TSS_REGISTER_ERROR( eEncoder(), _T("Display encoder error.") ) +TSS_REGISTER_ERROR( eBadDecoderInput(), _T("Bad input to display encoder.") ) +TSS_REGISTER_ERROR( eBadHexConversion(), _T("Bad hex conversion in display encoder.") ) +TSS_REGISTER_ERROR( eUnknownEscapeEncoding(), _T("Unknown encoding in display encoder input.") ) + + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/core/coreerrors.h b/src/core/coreerrors.h new file mode 100644 index 0000000..d9c51db --- /dev/null +++ b/src/core/coreerrors.h @@ -0,0 +1,48 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: coreerrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __COREERRORS_H +#define __COREERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( core ) + + +#endif//__COREERRORS_H + diff --git a/src/core/corestrings.cpp b/src/core/corestrings.cpp new file mode 100644 index 0000000..c407ad4 --- /dev/null +++ b/src/core/corestrings.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: corestrings.cpp +// Date....: 05/06/99 +// Creator.: Robert DiFalco (rdifalco) +// + +#include "stdcore.h" // for: pch (required by all core source modules) +#include "corestrings.h" // for: cCore and core::STR_IDS + + +TSS_BeginStringtable( cCore ) + + TSS_StringEntry( core::STR_ERR2_ARCH_CRYPTO_ERR, _T("File could not be decrypted.") ), + TSS_StringEntry( core::STR_ERR2_BAD_ARG_PARAMS, _T("Argument: ") ), + TSS_StringEntry( core::STR_ERROR_ERROR, _T("### Error") ), + TSS_StringEntry( core::STR_ERROR_WARNING, _T("### Warning") ), + TSS_StringEntry( core::STR_ERROR_COLON, _T(":") ), + TSS_StringEntry( core::STR_ERROR_HEADER, _T("### ") ), + TSS_StringEntry( core::STR_ERROR_EXITING, _T("Exiting...") ), + TSS_StringEntry( core::STR_ERROR_CONTINUING, _T("Continuing...") ), + TSS_StringEntry( core::STR_ERR2_FILENAME, _T("Filename: ") ), + TSS_StringEntry( core::STR_ERROR_FILENAME, _T("Filename: ") ), + TSS_StringEntry( core::STR_UNKNOWN, _T("Unknown") ), + TSS_StringEntry( core::STR_NUMBER_TOO_BIG, _T("Number too big") ), + TSS_StringEntry( core::STR_SIGNAL, _T("Software interrupt forced exit:") ), + TSS_StringEntry( core::STR_NEWLINE, _T("\n") ), + TSS_StringEntry( core::STR_MEMARCHIVE_FILENAME, _T("Error occured in internal memory file") ), + TSS_StringEntry( core::STR_MEMARCHIVE_ERRSTR, _T("") ), + TSS_StringEntry( core::STR_ENDOFTIME, _T("Tripwire is not designed to run past the year 2038.\nNow exiting...") ), + TSS_StringEntry( core::STR_UNKNOWN_TIME, _T("Unknown time") ), + TSS_StringEntry( core::STR_BAD_TEMPDIRECTORY, _T("Solution: Check existence/permissions for directory specified by TEMPDIRECTORY in config file") ), + /// Particularly useful for eCharacter and eCharacterEncoding + + TSS_StringEntry( core::STR_ERR_ISNULL, _T("Argument cannot be null.") ), + TSS_StringEntry( core::STR_ERR_OVERFLOW, _T("An overflow has been detected.") ), + TSS_StringEntry( core::STR_ERR_UNDERFLOW, _T("An underflow has been detected.") ), + TSS_StringEntry( core::STR_ERR_BADCHAR, _T("Input contained an invalid character.") ) + +TSS_EndStringtable( cCore ) + + +// eof: corestrings.cpp diff --git a/src/core/corestrings.h b/src/core/corestrings.h new file mode 100644 index 0000000..8164748 --- /dev/null +++ b/src/core/corestrings.h @@ -0,0 +1,81 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: corestrings.h +// Date....: 05/05/99 +// Creator.: Robert DiFalco (rdifalco) +// +// + +#ifndef __CORESTRINGS_H +#define __CORESTRINGS_H + + +#include "core.h" // for: STRINGTABLE syntax + + +//--Message Keys + +TSS_BeginStringIds( core ) + + STR_ERR2_ARCH_CRYPTO_ERR, + STR_ERR2_BAD_ARG_PARAMS, + STR_ERROR_ERROR, + STR_ERROR_WARNING, + STR_ERROR_COLON, + STR_ERROR_HEADER, + STR_ERROR_EXITING, + STR_ERROR_CONTINUING, + STR_ERR2_FILENAME, + STR_ERROR_FILENAME, + STR_NUMBER_TOO_BIG, + STR_UNKNOWN, + STR_SIGNAL, + STR_NEWLINE, + STR_MEMARCHIVE_FILENAME, + STR_MEMARCHIVE_ERRSTR, + STR_ENDOFTIME, + STR_UNKNOWN_TIME, + STR_BAD_TEMPDIRECTORY, + + /// Particularly useful for eCharacterSet and eCharacterEncoding + + STR_ERR_ISNULL, + STR_ERR_OVERFLOW, + STR_ERR_UNDERFLOW, + STR_ERR_BADCHAR + +TSS_EndStringIds( core ) + + +#endif //__CORESTRINGS_H + diff --git a/src/core/crc32.cpp b/src/core/crc32.cpp new file mode 100644 index 0000000..f8001bd --- /dev/null +++ b/src/core/crc32.cpp @@ -0,0 +1,177 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* - crc32.cpp + * + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James W. Williams of NASA Goddard Space Flight Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#include "../../include/config.h" +//#include +//#include +//#ifdef STDLIBH +//#include +//#include +//#endif +//#include "../../include/sigs.h" +#include "stdcore.h" +#include "crc32.h" + +#ifndef __ARCHIVE_H +#include "archive.h" +#endif + +#define BUFSIZE 4096 + +static uint32 crctab[] = { + 0x0, + 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, + 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, + 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, + 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, + 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, + 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, + 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, + 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, + 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, + 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, + 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, + 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, + 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, + 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, + 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, + 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, + 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, + 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, + 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, + 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, + 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, + 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, + 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, + 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, + 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, + 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, + 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, + 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, + 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, + 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, + 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, + 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, + 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, + 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +/* + * Compute a POSIX 1003.2 checksum. This routine has been broken out so that + * other programs can use it. It takes a file descriptor to read from and + * locations to store the crc and the number of bytes read. It returns 0 on + * success and 1 on failure. Errno is set on failure. + */ +#define COMPUTE(var, ch) (var) = ((var) << 8) ^ \ + crctab[0xff & (unsigned)((var) >> 24 ^ (ch))] + +void crcInit( CRC_INFO& crcInfo ) +{ + crcInfo.cbTotalLen = 0; + crcInfo.crc = 0; +} + +void crcUpdate( CRC_INFO& crcInfo, const uint8* pbData, int cbDataLen ) +{ + for( int i = 0; i < cbDataLen; i++, pbData++ ) + { + COMPUTE( crcInfo.crc, *pbData ); + } + + crcInfo.cbTotalLen += cbDataLen; +} + +void crcFinit( CRC_INFO& crcInfo ) +{ + // include the length + // + uint32 len = crcInfo.cbTotalLen; + for(; len != 0; len >>= 8) + COMPUTE( crcInfo.crc, len & 0xff ); + + crcInfo.crc = ~(crcInfo.crc) & 0xFFFFFFFF; +} + diff --git a/src/core/crc32.h b/src/core/crc32.h new file mode 100644 index 0000000..f297fbb --- /dev/null +++ b/src/core/crc32.h @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//crc32.h - Wimpy header file for crc32.cpp +#ifndef __CRC32_H +#define __CRC32_H + +class cArchive; + +typedef struct +{ + uint32 crc; + uint32 cbTotalLen; +} +CRC_INFO; + +// must have 8-bit bytes +void crcInit ( CRC_INFO& crcInfo ); +void crcUpdate( CRC_INFO& crcInfo, const uint8* pbData, int cbDataLen ); +void crcFinit ( CRC_INFO& crcInfo ); + + + // calculates the crc for len bytes starting at pBuf +//Wrapper function for CRC32 in crc32.cpp +#endif //__CRC32_H + diff --git a/src/core/debug.cpp b/src/core/debug.cpp new file mode 100644 index 0000000..6ccdada --- /dev/null +++ b/src/core/debug.cpp @@ -0,0 +1,528 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// debug.cpp +#include "stdcore.h" +#include "debug.h" +#include "errorutil.h" + + +#ifdef DEBUG + +#ifndef va_start +#include +#endif +#include +#include +#include + +int cDebug::mDebugLevel(10); +uint32 cDebug::mOutMask(cDebug::OUT_TRACE); +std::ofstream cDebug::logfile; + //mDebugLevel default == 10, mOutMask default == OUT_TRACE. + +/////////////////////////////////////////////////////////////////////////////// +// Constructors and Destructor +cDebug::cDebug(const char* label) +{ + int cnt = strlen(label); + if (cnt > cDebug::MAX_LABEL) + cnt = cDebug::MAX_LABEL - 1; + + memcpy(mLabel, label, cnt); + mLabel[cnt] = '\0'; +} + +cDebug::cDebug(const cDebug &rhs) +{ + strcpy(mLabel, rhs.mLabel); +} + +cDebug::~cDebug() +{ + if(logfile) + logfile.close(); +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Trace -- Outputs a format string only if the passed integer value is <= +// the "global debug level" (indicated by mDebugLevel). +/////////////////////////////////////////////////////////////////////////////// +void cDebug::Trace(int levelNum, const char* format, ...) +{ + if (levelNum > mDebugLevel) + return; + // create the output buffer + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); + +} + +void cDebug::Trace(int levelNum, const wchar_t* format, ...) +{ + if (levelNum > mDebugLevel) + return; + // create the output buffer + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); + +} + +/////////////////////////////////////////////////////////////////////////////// +// DoTrace() +// internal helper function -- does the actual printing to logfile, +// console, etc... +/////////////////////////////////////////////////////////////////////////////// + +void cDebug::DoTrace(const char *format, va_list &args) +{ + size_t guard1 = 0xBABABABA; + char out[2048]; + size_t guard2 = 0xBABABABA; + + vsprintf(out, format, args); + + ASSERT(guard1 == 0xBABABABA && guard2 == 0xBABABABA); // string was too long + ASSERT(strlen(out) < 1024); + + std::ostringstream ostr; + ostr.setf(std::ios::left); + ostr.width(40); + ostr << mLabel; + ostr.width(0); + ostr << out; + + + if ((mOutMask & OUT_STDOUT) != 0) + { + std::cout << ostr.str().c_str(); + std::cout.flush(); + } + + // + //make it output to log file! + // + if ((mOutMask & OUT_FILE) != 0) + { + // the logfile is narrow chars only... + logfile.setf(std::ios::left); + logfile.width(40); + logfile << mLabel; + logfile.width(0); + logfile << out; + logfile.flush(); + } +} + +void cDebug::DoTrace(const wchar_t *format, va_list &args) +{ +#if IS_UNIX + // we don't support vswprintf on UNIX + ASSERT(false); + THROW_INTERNAL("debug.cpp"); +#else + + size_t guard1 = 0xBABABABA; + wchar_t out[2048]; + size_t guard2 = 0xBABABABA; + + vswprintf(out, format, args); + + ASSERT(guard1 == 0xBABABABA && guard2 == 0xBABABABA); // string was too long + char nout[1024]; + if (wcstombs(nout, out, 1024) == -1) + strcpy(nout, "XXX Unconvertable wide char detected in cDebug::DoTrace()\n"); + + std::ostringstream ostr; + ostr.setf(std::ios::left); + ostr.width(40); + ostr << mLabel; + ostr.width(0); + ostr << nout; + + + if ((mOutMask & OUT_STDOUT) != 0) + { + std::cout << ostr.str().c_str(); + std::cout.flush(); + } + + // + //make it output to log file! + // + if ((mOutMask & OUT_FILE) != 0) + { + // the logfile is narrow chars only... + logfile.setf(std::ios::left); + logfile.width(40); + logfile << mLabel; + logfile.width(0); + logfile << out; + logfile.flush(); + } +#endif // IS_UNIX +} + +#ifdef DEBUG + +// +// wrappers around Trace() that requires less typing +// TODO: this is quick and dirty, but lets me check in all these files right away. --ghk +// + +void cDebug::TraceAlways(const char *format, ...) +{ + if (D_ALWAYS > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceError(const char *format, ...) +{ + if (D_ERROR > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceWarning(const char *format, ...) +{ + if (D_WARNING > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceDebug(const char *format, ...) +{ + if (D_DEBUG > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceDetail(const char *format, ...) +{ + if (D_DETAIL > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceNever(const char *format, ...) +{ + if (D_NEVER > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceAlways(const wchar_t *format, ...) +{ + if (D_ALWAYS > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceError(const wchar_t *format, ...) +{ + if (D_ERROR > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceWarning(const wchar_t *format, ...) +{ + if (D_WARNING > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceDebug(const wchar_t *format, ...) +{ + if (D_DEBUG > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceDetail(const wchar_t *format, ...) +{ + if (D_DETAIL > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceNever(const wchar_t *format, ...) +{ + if (D_NEVER > mDebugLevel) + return; + + // fill up arglist, and pass to printing routine + va_list args; + va_start(args, format); + DoTrace(format, args); + va_end(args); +} + +void cDebug::TraceVaArgs( int iDebugLevel, const char *format, va_list &args ) +{ + if ( iDebugLevel <= mDebugLevel ) + DoTrace( format, args); +} + +void cDebug::TraceVaArgs( int iDebugLevel, const wchar_t *format, va_list &args ) +{ + if ( iDebugLevel <= mDebugLevel ) + DoTrace( format, args ); +} + +#endif // DEBUG + +/////////////////////////////////////////////////////////////////////////////// +// AddOutTarget -- Attempts to add a new target for trace/debug output. +// FAILS ONLY IF caller attempts to SET OUT_FILE via this function. +/////////////////////////////////////////////////////////////////////////////// +bool cDebug::AddOutTarget(OutTarget target) +{ + if (target == OUT_STDOUT) + mOutMask |= OUT_STDOUT; + if (target == OUT_TRACE) + mOutMask |= OUT_TRACE; + if (target == OUT_FILE) { + mOutMask |= OUT_FILE; + return false; + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveOutTarget -- Masks out from mOutMask the value passed. +/////////////////////////////////////////////////////////////////////////////// +bool cDebug::RemoveOutTarget(OutTarget target) +{ + if (!HasOutTarget(target)) + return true; + if (target == OUT_STDOUT) + mOutMask ^= OUT_STDOUT; + if (target == OUT_TRACE) + mOutMask ^= OUT_TRACE; + if (target == OUT_FILE) + mOutMask ^= OUT_FILE; + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// HasOutTarget -- Takes target - target must represent a single flagged bit +/////////////////////////////////////////////////////////////////////////////// +bool cDebug::HasOutTarget(OutTarget target) +{ + + if (target == OUT_STDOUT) + return ((mOutMask & OUT_STDOUT) != 0); + else if (target == OUT_TRACE) + return ((mOutMask & OUT_TRACE) != 0); + else if (target == OUT_FILE) + return ((mOutMask & OUT_FILE) != 0); + else //ambiguous input, or too many bits set in target + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetOutputFile -- Attempts to set the output file for Logfile member to +// the string passed in. +/////////////////////////////////////////////////////////////////////////////// +bool cDebug::SetOutputFile(const char* filename) +{ + // TODO -- make sure this does the right thing if a log file is + // already open! + // TODO -- make this work with wide chars + if (!logfile) + logfile.open(filename, std::ios_base::out | std::ios_base::ate | std::ios_base::app); + else + logfile.setf(std::ios_base::hex, std::ios_base::basefield); + //make sure info. will not be clobbered. + + //Should be open now- if not, abort. + if (!logfile) { + mOutMask ^= OUT_FILE; + return false; + } else + mOutMask |= OUT_FILE; + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// DebugOut -- Works just like TRACE. note: there is an internal buffer size +// of 1024; traces larger than that will have unpredictable results. +////////////////////////////////////////////////////////////////////////////// +void cDebug::DebugOut( const char* lpOutputString, ... ) +{ + char buf[2048]; + // create the output buffer + va_list args; + va_start(args, lpOutputString); + vsprintf(buf, lpOutputString, args); + va_end(args); + +#ifdef _UNICODE + wchar_t wbuf[2048]; + if (mbstowcs(wbuf, buf, strlen(buf)+1) == -1) + wcscpy(wbuf, _T("XXX Unconvertable mb character detected in cDebug::DebugOut()\n") ); + + #if !USE_OUTPUT_DEBUG_STRING + #ifdef _DEBUG + TCERR << wbuf; + #endif //_DEBUG + #else // USE_OUTPUT_DEBUG_STRING + ::OutputDebugString(wbuf); + #endif // USE_OUTPUT_DEBUG_STRING +#else // _UNICODE + #if !USE_OUTPUT_DEBUG_STRING + #ifdef _DEBUG + TCERR << buf; + #endif //_DEBUG + #else // USE_OUTPUT_DEBUG_STRING + ::OutputDebugString(buf); + #endif // USE_OUTPUT_DEBUG_STRING +#endif // _UNICODE + + TCOUT.flush(); +} + +void cDebug::DebugOut( const wchar_t* lpOutputString, ... ) +{ + va_list args; + va_start(args, lpOutputString); + +#if IS_UNIX + char mbformatbuf[1024]; + char buf[1024]; +// if (wcstombs(mbformatbuf, lpOutputString, wcslen(lpOutputString)) == -1) +// strcpy(mbformatbuf, "XXX Unconvertable wide char detected in cDebug::DebugOut()\n"); + + vsprintf(buf, mbformatbuf, args); +#else + + wchar_t buf[1024]; + vswprintf(buf, lpOutputString, args); +#endif + va_end(args); + +#ifdef _UNICODE + #if !USE_OUTPUT_DEBUG_STRING + #ifdef _DEBUG + TCERR << buf; + #endif //_DEBUG + #else // USE_OUTPUT_DEBUG_STRING + ::OutputDebugString(buf); + #endif // USE_OUTPUT_DEBUG_STRING +#else + char nbuf[1024]; + #if IS_UNIX + strcpy(nbuf, buf); + #else + if (wcstombs(nbuf, buf, wcslen(buf)+1) == -1) + strcpy(nbuf, "XXX Unconvertable wide char detected in cDebug::DebugOut()\n"); +#endif + +#if !USE_OUTPUT_DEBUG_STRING + #ifdef _DEBUG + TCERR << nbuf; + #endif //_DEBUG +#else // USE_OUTPUT_DEBUG_STRING + ::OutputDebugString(nbuf); +#endif // USE_OUTPUT_DEBUG_STRING + #endif + + TCOUT.flush(); +} + +#endif // DEBUG + +////////////////////////////////////////////////////////////////////////////////// +// ASSERT macro support function +////////////////////////////////////////////////////////////////////////////////// + diff --git a/src/core/debug.h b/src/core/debug.h new file mode 100644 index 0000000..b38a8da --- /dev/null +++ b/src/core/debug.h @@ -0,0 +1,253 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// debug.h +// +// definitions of debug macros that will vary across platforms + +#ifndef __DEBUG_H +#define __DEBUG_H + +#include + + + + +#include +/* Do it in this order, because autoconf checks for + * first i.e. if HAVE_VARARGS_H is defined, it is only because + * couldn't be found. + */ +#ifdef HAVE_VARARGS_H +# include +#else +# ifdef HAVE_STDARG_H +# include +# endif +#endif +#include "types.h" + +// +// NOTE: +// When compiling with MFC, these are already defined and we get error msgs +// every time this file is included. Since these behave the same as the MFC +// version, it is OK to always undef them here.... +// -- 20 Aug 99 mdb +// +#undef ASSERT +#undef TRACE + +// +// IMPORTANT: +// +// strings outputted as trace statements are printed as narrow characters. +// passing trace messages with wide characters will have odd results, since +// they will be used as arugments to sprintf(), etc... +// + +// debug utility class +class cDebug +{ +public: + enum OutTarget + { + OUT_STDOUT = 1, + OUT_TRACE = 2, + OUT_FILE = 4 + }; + + enum DebugLevel + { + D_ALWAYS = 0, + D_ERROR = 1, + D_WARNING = 4, + D_DEBUG = 8, + D_DETAIL = 16, + D_NEVER = 1000 + }; + + cDebug(const char* pLabel); + ~cDebug(); + cDebug(const cDebug& rhs); + + // These are the preferred tracing interfaces, because you don't need to know + // the DebugLevel enums. + // Wide/Narrow Chars Issues: If you include a %s in your format string and you + // wish to print out a TCHAR (which might be a natural thing to do) you should + // encompas the format string with a _T("") macro, i.e. make it a TSTRING. + // The wide character overloads of these functions will expect wide strings + // for %s options. + // + void TraceAlways (const char *format, ...); + void TraceError (const char *format, ...); + void TraceWarning (const char *format, ...); + void TraceDebug (const char *format, ...); + void TraceDetail (const char *format, ...); + void TraceNever (const char *format, ...); + void TraceAlways (const wchar_t *format, ...); + void TraceError (const wchar_t *format, ...); + void TraceWarning (const wchar_t *format, ...); + void TraceDebug (const wchar_t *format, ...); + void TraceDetail (const wchar_t *format, ...); + void TraceNever (const wchar_t *format, ...); + + // these are of use if you are inside a function with a "..." as an argument + // and you want to trace those args + void TraceVaArgs (int iDebugLevel, const char *format, va_list &args); + void TraceVaArgs (int iDebugLevel, const wchar_t *format, va_list &args); + + // ...but you can still choose to use this interface... + + void Trace(int levelNum, const char* format, ...); + void Trace(int levelNum, const wchar_t* format, ...); + // Outputs based on levelnum. If levelnum <= global debug, print. + +public: + + static bool AddOutTarget (OutTarget target); + static bool RemoveOutTarget (OutTarget target); + // used to specify the out target.... + static bool HasOutTarget (OutTarget target); + + static bool SetOutputFile (const char* filename); + // specifies the output file name used when OUT_FILE is set + static void SetDebugLevel (int level); + static int GetDebugLevel (void); + // gets and sets the global debug level. Trace output at or below this + // level will be output. + + static void DebugOut ( const char* lpOutputString, ... ); + static void DebugOut ( const wchar_t* lpOutputString, ... ); + // Works just like TRACE + // note: there is an internal buffer size of 1024; traces larger + // than that will have unpredictable and probably bad results +private: +#ifdef DEBUG + enum { MAX_LABEL = 128 }; + + static int mDebugLevel; + static uint32 mOutMask; + static std::ofstream logfile; + char mLabel[MAX_LABEL]; + + // helper functions + void DoTrace(const char *format, va_list &args); + void DoTrace(const wchar_t *format, va_list &args); +#endif +}; + +#ifdef _DEBUG +#define TRACE cDebug::DebugOut +#else +#define TRACE 1 ? (void)0 : cDebug::DebugOut +#endif // _DEBUG + +////////////////////////////////////////////////////////////////////////////////// +// inline implementation +////////////////////////////////////////////////////////////////////////////////// +// Hopefully this class should do nothing in release mode + +#ifdef DEBUG + +inline void cDebug::SetDebugLevel(int level) +{ + mDebugLevel = level; +} + +inline int cDebug::GetDebugLevel() +{ + return mDebugLevel; +} + +#else // DEBUG + +inline cDebug::cDebug (const char *pLabel) {} +inline cDebug::~cDebug () {} +inline cDebug::cDebug (const cDebug& rhs) {} +inline void cDebug::TraceAlways (const char *format, ...) {} +inline void cDebug::TraceError (const char *format, ...) {} +inline void cDebug::TraceWarning (const char *format, ...) {} +inline void cDebug::TraceDebug (const char *format, ...) {} +inline void cDebug::TraceDetail (const char *format, ...) {} +inline void cDebug::TraceNever (const char *format, ...) {} +inline void cDebug::TraceAlways (const wchar_t *format, ...) {} +inline void cDebug::TraceError (const wchar_t *format, ...) {} +inline void cDebug::TraceWarning (const wchar_t *format, ...) {} +inline void cDebug::TraceDebug (const wchar_t *format, ...) {} +inline void cDebug::TraceDetail (const wchar_t *format, ...) {} +inline void cDebug::TraceNever (const wchar_t *format, ...) {} +inline void cDebug::TraceVaArgs (int iDebugLevel, const char *format, va_list &args) {} +inline void cDebug::TraceVaArgs (int iDebugLevel, const wchar_t *format, va_list &args) {} +inline void cDebug::Trace (int levelNum, const char* format, ...) {} +inline void cDebug::Trace (int levelNum, const wchar_t* format, ...) {} +inline bool cDebug::AddOutTarget (OutTarget target) { return false; } +inline bool cDebug::RemoveOutTarget (OutTarget target) { return false; } +inline bool cDebug::HasOutTarget (OutTarget target) { return false; } +inline bool cDebug::SetOutputFile (const char* filename) { return false; } +inline void cDebug::SetDebugLevel (int level) {} +inline int cDebug::GetDebugLevel (void) { return 0; } +inline void cDebug::DebugOut ( const char* lpOutputString, ... ) {} +inline void cDebug::DebugOut ( const wchar_t* lpOutputString, ... ) {} + +#endif // DEBUG + + + +////////////////////////////////////////////////////////////////////////////////// +// ASSERT macro +////////////////////////////////////////////////////////////////////////////////// + + +#if IS_UNIX + + #define ASSERTMSG( exp, s ) assert( (exp) != 0 ) + #define ASSERT( exp ) assert( (exp) != 0 ) + // if we are not windows we will just use the standard assert() + #define TSS_DebugBreak() ASSERT( false ); + +#endif// IS_UNIX + + +#ifndef ASSERT +#error ASSERT did not get defined!!! +#endif + +#ifndef ASSERTMSG +#error ASSERTMSG did not get defined!!! +#endif + +#ifndef TSS_DebugBreak +#error TSS_DebugBreak did not get defined!!! +#endif + +#endif //__DEBUG_H + diff --git a/src/core/debug_t.cpp b/src/core/debug_t.cpp new file mode 100644 index 0000000..a205f84 --- /dev/null +++ b/src/core/debug_t.cpp @@ -0,0 +1,90 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// debug_t -- debug component test driver + +#include "stdcore.h" +#include "debug.h" +#include "test/test.h" + +void TestDebug() +{ + // it is amusing that we use cDebug to output the results of testing cDebug + // "Are you insane?" ... "No, I am not." + cDebug d("TestDebug()"); + d.TraceDebug("Entering..."); + + // save the current debug level, since we will be altering it. + int oldDebugLevel = cDebug::GetDebugLevel(); + + // test debug level variation... + d.TraceDebug("Setting debug level to Debug(%d)\n", cDebug::D_DEBUG); + cDebug::SetDebugLevel(cDebug::D_DEBUG); + d.TraceDebug ("You should see this, as well as line 2 below, but not line 3.\n"); + d.TraceWarning ("Line 2: Warning(%d)\n", cDebug::D_WARNING); + d.TraceDetail ("Line 3: Detail(%d)\n", cDebug::D_DETAIL); + d.TraceDebug ("Restoring the debug level to %d\n", oldDebugLevel); + cDebug::SetDebugLevel(oldDebugLevel); + + // testing the output source + int oldOutTarget = 0; + if(cDebug::HasOutTarget(cDebug::OUT_STDOUT)) oldOutTarget |= cDebug::OUT_STDOUT; + if(cDebug::HasOutTarget(cDebug::OUT_TRACE)) oldOutTarget |= cDebug::OUT_TRACE; + if(cDebug::HasOutTarget(cDebug::OUT_FILE)) oldOutTarget |= cDebug::OUT_FILE; + cDebug::RemoveOutTarget(cDebug::OUT_STDOUT); + cDebug::RemoveOutTarget(cDebug::OUT_TRACE); + cDebug::RemoveOutTarget(cDebug::OUT_FILE); + + d.TraceDebug("You should not see this (All out targets removed)\n"); + cDebug::AddOutTarget(cDebug::OUT_STDOUT); + d.TraceDebug("You should see this in stdout only.\n"); + cDebug::AddOutTarget(cDebug::OUT_TRACE); + d.TraceDebug("You should see this in stdout and trace.\n"); + cDebug::RemoveOutTarget(cDebug::OUT_STDOUT); + d.TraceDebug("You should see this in trace only.\n"); + // set up an output file...use the temp file in test.h + std::string str = TEMP_DIR_N; + str += "/debug.out"; + bool bResult = false; + bResult = cDebug::SetOutputFile(str.c_str()); + TEST(bResult); + d.TraceDebug("This should be in trace and the file %s.\n", str.c_str()); + + // restore the out source... + // TODO -- note that the original output file cannot be restored; this sucks! + if(oldOutTarget & cDebug::OUT_STDOUT) cDebug::AddOutTarget(cDebug::OUT_STDOUT); else cDebug::RemoveOutTarget(cDebug::OUT_STDOUT); + if(oldOutTarget & cDebug::OUT_TRACE) cDebug::AddOutTarget(cDebug::OUT_TRACE); else cDebug::RemoveOutTarget(cDebug::OUT_TRACE); + if(oldOutTarget & cDebug::OUT_FILE) cDebug::AddOutTarget(cDebug::OUT_FILE); else cDebug::RemoveOutTarget(cDebug::OUT_FILE); + + d.TraceDebug("Exiting...\n"); +} + + diff --git a/src/core/displayencoder.cpp b/src/core/displayencoder.cpp new file mode 100644 index 0000000..b680f7d --- /dev/null +++ b/src/core/displayencoder.cpp @@ -0,0 +1,916 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// displayencoder.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdcore.h" +#include "displayencoder.h" +#include "charutil.h" +#include "debug.h" +#include "twlocale.h" +#include "stringutil.h" +#include "errorutil.h" +#include "ntmbs.h" +#include "codeconvert.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include +#include + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +// uncomment this to test schema +// #define TSS_DO_SCHEMA_VALIDATION + +////////////////////////////////////////////////////////////////////////////// +// ENCODER UTILITIES +////////////////////////////////////////////////////////////////////////////// + + +inline bool IsSingleTCHAR( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( first + 1 == last ); +} + +////////////////////////////////////////////////////////////////////////////// +// CHAR ENCODER INTERFACE +////////////////////////////////////////////////////////////////////////////// + +// all derived classes should encode a char to "EscapeChar() + Identifier() + Encode( char ) [ + Identifier() ]" + +class iCharEncoder +{ + public: + virtual bool NeedsEncoding( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const = 0; + // Determines if character identified by [first,last) needs encoding. + // Returns true if it does. + + virtual TSTRING EncodeRoundtrip(TSTRING::const_iterator first, + TSTRING::const_iterator last ) const = 0; + // Encodes character identified by [first,last) in such a way that it + // can be decoded by Decode(). Returns encoded character sequence. + + virtual TSTRING EncodePretty( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const = 0; + // Encodes character identified by [first,last) in a manner that is not roundtrip, + // but looks good. Returns encoded character sequence. + + virtual TSTRING Decode( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) const = 0; + // Decodes character sequence beginning with '*pcur' and ending before 'end'. + // Returns decoded character or sequence of characters. Advances *pcur beyond + // the last character decoded. + + + virtual TCHAR Identifier() const = 0; + + static TCHAR EscapeChar() { return char_escape; } + + protected: + + static TCHAR char_escape; +}; + + +class cNonNarrowableCharEncoder : public iCharEncoder +{ + public: + virtual bool NeedsEncoding( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodeRoundtrip(TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodePretty( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING Decode( TSTRING::const_iterator* cur, + const TSTRING::const_iterator end ) const; + + virtual TCHAR Identifier() const; + private: + static TCHAR char_identifier; + static TCHAR char_replace; +}; + + +class cNonPrintableCharEncoder : public iCharEncoder +{ + public: + cNonPrintableCharEncoder( bool f_allowWS ) + : m_allowWS( f_allowWS ) {}; + + virtual bool NeedsEncoding( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodeRoundtrip(TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodePretty( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING Decode( TSTRING::const_iterator* cur, + const TSTRING::const_iterator end ) const; + + virtual TCHAR Identifier() const; + private: + static TCHAR char_identifier; + static TCHAR char_replace; + + bool m_allowWS; +}; + +class cQuoteCharEncoder : public iCharEncoder +{ + public: + virtual bool NeedsEncoding( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodeRoundtrip(TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodePretty( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING Decode( TSTRING::const_iterator* cur, + const TSTRING::const_iterator end ) const; + + virtual TCHAR Identifier() const; + private: + static TCHAR char_test; + static TCHAR char_identifier; + static TCHAR char_replace; +}; + + +class cBackslashCharEncoder : public iCharEncoder +{ + public: + virtual bool NeedsEncoding( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodeRoundtrip(TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING EncodePretty( TSTRING::const_iterator first, + TSTRING::const_iterator last ) const; + + virtual TSTRING Decode( TSTRING::const_iterator* cur, + const TSTRING::const_iterator end ) const; + + virtual TCHAR Identifier() const; + private: + static TCHAR char_test; + static TCHAR char_identifier; + static TCHAR char_replace; +}; + + +////////////////////////////////////////////////////////////////////////////// +// CHARACTER SPECIALIZATIONS +////////////////////////////////////////////////////////////////////////////// + +TCHAR iCharEncoder::char_escape = _T('\\'); + +TCHAR cNonNarrowableCharEncoder::char_identifier = _T('x'); +TCHAR cNonPrintableCharEncoder::char_identifier = _T('x'); +TCHAR cQuoteCharEncoder::char_identifier = _T('\"'); +TCHAR cBackslashCharEncoder::char_identifier = _T('\\'); + +TCHAR cBackslashCharEncoder::char_test = cBackslashCharEncoder::char_identifier; +TCHAR cQuoteCharEncoder::char_test = cQuoteCharEncoder::char_identifier; + +TCHAR cBackslashCharEncoder::char_replace = cBackslashCharEncoder::char_identifier; +TCHAR cQuoteCharEncoder::char_replace = cQuoteCharEncoder::char_identifier; + +TCHAR cNonNarrowableCharEncoder::char_replace = _T('?'); +TCHAR cNonPrintableCharEncoder::char_replace = _T('?'); + +////////////////////////////////////////////////////////////////////////////// +// TESTS +////////////////////////////////////////////////////////////////////////////// + +bool cNonNarrowableCharEncoder::NeedsEncoding( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + +#ifdef _UNICODE + + ASSERT( IsSingleTCHAR( first, last ) ); + + char amb[ MB_LEN_MAX ]; + TCHAR awch[] = { *first, 0 }; + + // TODO:BAM -- this is not really correct! Convert will not honor nSource!! + // it looks for the first null char! + try + { + int ret = iCodeConverter::GetInstance()->Convert( amb, sizeof( amb ), awch, 1 ); + return( -1 == ret ); + } + catch( eError& ) + { + return true; + } + +#else + + return false; // all chars are narrow + +#endif + +} + + + +bool cNonPrintableCharEncoder::NeedsEncoding( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + // TODO:BAM -- handle this with mb chars + // std::isprint does a wctob() on the wchar!!?!?! + // what's up with that? Maybe ignore this all together and + // just do a isprint like KAI does? + + // HYPOTHESIS: all mb characters are printable. only sb ASCII + // chars that would have C isprint() return false actually aren't printable + // So escape chars, and tabs and such are only in sb chars that C isprint() would check. + // HMMMM: true in all locales, though? (LC_CTYPE is checked for C isprint(), though...) + + // Sooooo... it should be something like + // + // #ifdef _UNICODE + // char nch = wctob( ch ); + // return( nch != EOF && ! isprint( nch ) ); + // #else + // return( ! isprint( ch ) ); + // #endif + // + + // assuming all unprintable chars are one TCHAR long + if( ! IsSingleTCHAR( first, last ) ) + return false; + + if( m_allowWS && cCharEncoderUtil::IsWhiteSpace( *first ) ) + return false; + + return cCharEncoderUtil::IsPrintable( *first ); +} + +bool cQuoteCharEncoder::NeedsEncoding( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + return( + IsSingleTCHAR( first, last ) + && + ( *first == char_test ) + ); +} + +bool cBackslashCharEncoder::NeedsEncoding( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + return( + IsSingleTCHAR( first, last ) + && + ( *first == char_test ) + ); +} + +////////////////////////////////////////////////////////////////////////////// +// ROUNDTRIP ENCODINGS +////////////////////////////////////////////////////////////////////////////// + + +TSTRING cNonNarrowableCharEncoder::EncodeRoundtrip( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + TSTRING str; + + str += char_escape; + str += char_identifier; + str += cCharEncoderUtil::CharStringToHexValue( TSTRING( first, last ) ); + + return str; +} + + +TSTRING cNonPrintableCharEncoder::EncodeRoundtrip( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + ASSERT( IsSingleTCHAR( first, last ) ); // non-prints are single char (see NOTE above) + + TSTRING str; + + str += char_escape; + str += char_identifier; + str += cCharEncoderUtil::CharStringToHexValue( TSTRING( first, last ) ); + + return str; +} + + +TSTRING cQuoteCharEncoder::EncodeRoundtrip( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + // should just be a quote + ASSERT( IsSingleTCHAR( first, last ) ); + ASSERT( *first == char_test ); + + TSTRING str; + + str += char_escape; + str += char_identifier; + + return str; +} + + + +TSTRING cBackslashCharEncoder::EncodeRoundtrip( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + // should just be a backslash + ASSERT( IsSingleTCHAR( first, last ) ); + ASSERT( *first == char_test ); + + TSTRING str; + + str += char_escape; + str += char_identifier; + + return str; +} + +////////////////////////////////////////////////////////////////////////////// +// NON-ROUNDTRIP ENCODINGS +////////////////////////////////////////////////////////////////////////////// + + +TSTRING cNonNarrowableCharEncoder::EncodePretty( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + return EncodeRoundtrip( first, last ); +} + + +TSTRING cNonPrintableCharEncoder::EncodePretty( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + return EncodeRoundtrip( first, last ); +} + + +TSTRING cQuoteCharEncoder::EncodePretty( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + // should just be a quote + ASSERT( IsSingleTCHAR( first, last ) ); + ASSERT( *first == char_test ); + + return TSTRING( 1, char_replace ); +} + + +TSTRING cBackslashCharEncoder::EncodePretty( + TSTRING::const_iterator first, + TSTRING::const_iterator last ) const +{ + // should just be a backslash + ASSERT( IsSingleTCHAR( first, last ) ); + ASSERT( *first == char_test ); + + return TSTRING( 1, char_replace ); +} + +////////////////////////////////////////////////////////////////////////////// +// DECODINGS +////////////////////////////////////////////////////////////////////////////// + + +TSTRING cNonNarrowableCharEncoder::Decode( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) const +{ + // check preconditions + if( (*pcur) >= end || *(*pcur) != Identifier() ) + ThrowAndAssert( eBadDecoderInput() ); + + return( cCharEncoderUtil::DecodeHexToChar( pcur, end ) ); +} + + +TSTRING cNonPrintableCharEncoder::Decode( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) const +{ + // check preconditions + if( (*pcur) >= end || *(*pcur) != Identifier() ) + ThrowAndAssert( eBadDecoderInput() ); + + return( cCharEncoderUtil::DecodeHexToChar( pcur, end ) ); +} + + +TSTRING cQuoteCharEncoder::Decode( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) const +{ + if( (*pcur) >= end || *(*pcur) != Identifier() ) + ThrowAndAssert( eBadDecoderInput() ); + + (*pcur)++; // advance past part decoded + + return TSTRING( 1, Identifier() ); +} + + +TSTRING cBackslashCharEncoder::Decode( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) const +{ + if( (*pcur) >= end || *(*pcur) != Identifier() ) + ThrowAndAssert( eBadDecoderInput() ); + + (*pcur)++; // advance past part decoded + + return TSTRING( 1, Identifier() ); +} + +////////////////////////////////////////////////////////////////////////////// +// IDENTIFIERS +////////////////////////////////////////////////////////////////////////////// + + +TCHAR cNonNarrowableCharEncoder::Identifier() const +{ + return char_identifier; +} + + +TCHAR cNonPrintableCharEncoder::Identifier() const +{ + return char_identifier; +} + + +TCHAR cQuoteCharEncoder::Identifier() const +{ + return char_identifier; +} + +TCHAR cBackslashCharEncoder::Identifier() const +{ + return char_identifier; +} + +////////////////////////////////////////////////////////////////////////////// +// UTILITIES +////////////////////////////////////////////////////////////////////////////// + +bool cCharEncoderUtil::IsWhiteSpace( TCHAR ch ) +{ + return ( ch == '\r' || + ch == '\n' || + ch == '\t' || + ch == '\v' || + ch == ' ' ); +} + +bool cCharEncoderUtil::IsPrintable( TCHAR ch ) +{ +#if USE_CLIB_LOCALE && !defined(__APPLE__) + + return( ! isprint( ch ) ); // kludge for KAI + +#else // USE_CLIB_LOCALE + +#if IS_UNIX + return( ! std::isprint( ch, std::locale() ) ); + + #endif + +#endif // USE_CLIB_LOCALE +} + +TSTRING cCharEncoderUtil::CharStringToHexValue( const TSTRING& str ) +{ + TSTRING strOut; + TSTRING::const_iterator at; + + for( at = str.begin(); at < str.end(); at++ ) + { + strOut += char_to_hex( *at ); + } + + return strOut; +} + + +TSTRING cCharEncoderUtil::HexValueToCharString( const TSTRING& str ) +{ + TSTRING strOut; + TSTRING::const_iterator at; + + for( at = str.begin(); at < str.end(); at += TCHAR_AS_HEX__IN_TCHARS ) + { + strOut += hex_to_char( at, at + TCHAR_AS_HEX__IN_TCHARS ); + } + + return strOut; +} + +TCHAR cCharEncoderUtil::hex_to_char( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + static const TCHAR max_char = std::numeric_limits::max(); + static const TCHAR min_char = std::numeric_limits::min(); + + if( first + TCHAR_AS_HEX__IN_TCHARS != last ) + ThrowAndAssert( eBadHexConversion() ); + + TISTRINGSTREAM ss( TSTRING( first, last ) ); + ss.imbue( std::locale::classic() ); + ss.fill ( _T('0') ); + ss.setf( std::ios_base::hex, std::ios_base::basefield ); + + unsigned long ch; + ss >> ch; + + if( ss.bad() || ss.fail() ) + ThrowAndAssert( eBadHexConversion( TSTRING( first, last ) ) ); + if( (TCHAR)ch > max_char || (TCHAR)ch < min_char ) + ThrowAndAssert( eBadHexConversion( TSTRING( first, last ) ) ); + + return (TCHAR)ch; +} + + +TSTRING cCharEncoderUtil::char_to_hex( TCHAR ch ) +{ + TOSTRINGSTREAM ss; + + ss.imbue( std::locale::classic() ); + ss.fill ( _T('0') ); + ss.width( TCHAR_AS_HEX__IN_TCHARS ); + ss.setf( std::ios_base::hex, std::ios_base::basefield ); + + ss << tss::util::char_to_size( ch ); + + if( ss.bad() || ss.fail() || + ss.str().length() != TCHAR_AS_HEX__IN_TCHARS ) + ThrowAndAssert( eBadHexConversion( TSTRING( 1, ch ) ) ); + return ss.str(); +} + +TSTRING cCharEncoderUtil::DecodeHexToChar( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ) +{ + // get hex numbers -- 2 chars + TSTRING str; + size_t n = 0; + for( (*pcur)++; + n < TCHAR_AS_HEX__IN_TCHARS && + (*pcur) != end; + n++, (*pcur)++ ) + { + str += *(*pcur); + } + + if( n != TCHAR_AS_HEX__IN_TCHARS ) + ThrowAndAssert( eBadDecoderInput() ); + + // convert hex numbers + return HexValueToCharString( str ); +} + +////////////////////////////////////////////////////////////////////////////// +// ENCODER MEMBERS +////////////////////////////////////////////////////////////////////////////// + + +cEncoder::cEncoder( int e, int f ) + : m_fFlags( f ) +{ + // add encodings + if( e & NON_NARROWABLE ) + m_encodings.push_back( new cNonNarrowableCharEncoder ); + if( e & NON_PRINTABLE ) + m_encodings.push_back( new cNonPrintableCharEncoder( AllowWhiteSpace() ) ); + if( e & BACKSLASH ) + m_encodings.push_back( new cBackslashCharEncoder ); + if( e & DBL_QUOTE ) + m_encodings.push_back( new cQuoteCharEncoder ); + + // assert that we weren't passed anything freaky + ASSERT( 0 == ( e & ~( NON_NARROWABLE | + NON_PRINTABLE | + BACKSLASH | + DBL_QUOTE ) ) ); + + // add flags + ASSERT( ! ( ( m_fFlags & ROUNDTRIP ) && + ( m_fFlags & NON_ROUNDTRIP ) ) ); + +#ifdef TSS_DO_SCHEMA_VALIDATION + + // check assumptions about encodings + ValidateSchema(); + +#endif + +} + + +cEncoder::~cEncoder() +{ +} + +bool cEncoder::RoundTrip() const +{ + return( 0 != ( m_fFlags & ROUNDTRIP ) ); +} + +bool cEncoder::AllowWhiteSpace() const +{ + return( 0 != ( m_fFlags & ALLOW_WHITESPACE ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// ENCODER BASIC FUNCTIONALITY +////////////////////////////////////////////////////////////////////////////// + +void cEncoder::Encode( TSTRING& strIn ) const +{ + // TODO:BAM -- reserve space for strOut as an optimization? + TSTRING strOut; // encoded string we will build up + + TSTRING::const_iterator cur = strIn.begin(); // pointer to working position in strIn + const TSTRING::const_iterator end = strIn.end(); // end of strIn + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + // while get next char (updates cur) + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + bool fCharEncoded = false; // answers: did char need encoding? + sack_type::const_iterator atE; + + // for all encoders + for( atE = m_encodings.begin(); + atE != m_encodings.end(); + atE++ ) + { + // does char need encoding? + if( (*atE)->NeedsEncoding( first, last ) ) + { + strOut += Encode( first, last, atE ); + fCharEncoded = true; + break; // each char should only fail at most one + // encoding test, so it should be cool to quit + } + } + + if( ! fCharEncoded ) + { + strOut.append( first, last ); // simply add current char to output since it needed no encoding + } + } + + // pass back encoded string + strIn = strOut; +} + +TSTRING cEncoder::Encode( TSTRING::const_iterator first, + TSTRING::const_iterator last, + sack_type::const_iterator encoding ) const +{ + // encode it + if( RoundTrip() ) + return (*encoding)->EncodeRoundtrip( first, last ); + else + return (*encoding)->EncodePretty( first, last ); +} + +void cEncoder::Decode( TSTRING& strIn ) const +{ + // TODO:BAM -- reserve space for strOut as an optimization? + TSTRING strOut; // decoded string we will build up + + TSTRING::const_iterator cur = strIn.begin(); // pointer to working position in strIn + const TSTRING::const_iterator end = strIn.end(); // end of strIn + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + + // while get next char (updates cur) + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + // is this char the escape character? + if( IsSingleTCHAR( first, last ) && + *first == iCharEncoder::EscapeChar() ) + { + // get to identifier + if( ! cCharUtil::PopNextChar( cur, end, first, last ) ) + ThrowAndAssert( eBadDecoderInput() ); + + // this algorithm assumes that all identifiers are single char + // so anything following the escape char should be a + // single-char identifier + if( ! IsSingleTCHAR( first, last ) ) + THROW_INTERNAL( "displayencoder.cpp" ); + + // determine to which encoding the identifier belongs + bool fFoundEncoding = false; + sack_type::const_iterator atE; + for( atE = m_encodings.begin(); + atE != m_encodings.end(); + atE++ ) + { + // is this the right encoding? + if( *first == (*atE)->Identifier() ) + { + // this is the correct encoding.... + fFoundEncoding = true; + + // ...so decode char + strOut += (*atE)->Decode( &first, end ); // should modify cur + + cur = first; // advance current char pointer + + break; // no need to run other tests after + // this because all identifiers should be unique + } + } + + if( ! fFoundEncoding ) + ThrowAndAssert( eUnknownEscapeEncoding( TSTRING( 1, *first ) ) ); + } + else + { + strOut.append( first, last ); + } + } + + strIn = strOut; +} + +////////////////////////////////////////////////////////////////////////////// +// ENCODER SCHEMA VALIDATION +////////////////////////////////////////////////////////////////////////////// + +void cEncoder::ValidateSchema() const +{ + ASSERT( OnlyOneCatagoryPerChar() ); + ASSERT( AllIdentifiersUnique() ); +} + + +// only tests single TCHAR characters (but of those, tests all of them) +bool cEncoder::OnlyOneCatagoryPerChar() const +{ + // TODO:BAM - man, is there a better way to do this? + TCHAR ach[2] = {0}; + TCHAR ch = std::numeric_limits::min(); + if( ch != std::numeric_limits::max() ) + { + do + { + bool fFailedATest = false; + + ach[0] = ch; + for( sack_type::const_iterator atE = m_encodings.begin(); atE != m_encodings.end(); atE++ ) + { + TSTRING::const_iterator first(&ach[0]), last(&ach[1]); + if( (*atE)->NeedsEncoding( first, last ) ) + { + if( fFailedATest ) + return false; // each char can only fail one test + else + fFailedATest = true; + } + } + ch++; + } + while( ch != std::numeric_limits::max() ); + } + return true; +} + + +bool cEncoder::AllIdentifiersUnique() const +{ + TSTRING chars; + for( sack_type::const_iterator atE = m_encodings.begin(); atE != m_encodings.end(); atE++ ) + { + TCHAR chID = (*atE)->Identifier(); + if( chars.find( chID ) == TSTRING::npos ) + chars += chID; + else + return false; + } + return true; +} + + +bool cEncoder::AllTestsRunOnEncodedString( const TSTRING& s ) const +{ + TSTRING::const_iterator cur = s.begin(); // pointer to working position in s + const TSTRING::const_iterator end = s.end(); // end of s + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + + // while get next char (updates cur) + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + sack_type::const_iterator atE; + for( atE = m_encodings.begin(); + atE != m_encodings.end(); + atE++ ) + { + if( (*atE)->NeedsEncoding( first, last ) ) + { + return false; + } + } + } + + return true; +} + + +////////////////////////////////////////////////////////////////////////////// +// cDisplayEncoder MEMBERS +////////////////////////////////////////////////////////////////////////////// + + +cDisplayEncoder::cDisplayEncoder( Flags f ) + : cEncoder( + NON_NARROWABLE | + NON_PRINTABLE | + BACKSLASH | + DBL_QUOTE, + f + ) +{ +} + +void cDisplayEncoder::Encode( TSTRING& str ) const +{ + cEncoder::Encode( str ); +} + +bool cDisplayEncoder::Decode( TSTRING& str ) const +{ + cEncoder::Decode( str ); + return true; // TODO:BAM -- throw error! +} + diff --git a/src/core/displayencoder.h b/src/core/displayencoder.h new file mode 100644 index 0000000..fb8a775 --- /dev/null +++ b/src/core/displayencoder.h @@ -0,0 +1,244 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// displayencoder.h +// + +#ifndef __DISPLAYENCODER_H +#define __DISPLAYENCODER_H + +//========================================================================= +// EXCEPTION DECLARATION +//========================================================================= + +TSS_EXCEPTION( eEncoder, eError ); +TSS_EXCEPTION( eBadDecoderInput, eEncoder ); +TSS_EXCEPTION( eBadHexConversion, eEncoder ); +TSS_EXCEPTION( eUnknownEscapeEncoding, eEncoder ); + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +/////////////////////////////////////////////// +// cDisplayEncoder +/////////////////////////////////////////////// + +class iCharEncoder; + +// TODO:BAM -- i don't think that the order of encodings is important +// as long as AllIdentifiersUnique and OnlyOneCatagoryPerChar are true +class cEncoder +{ + public: + enum Encodings + { + NON_NARROWABLE = 0x01, // WC -> MB, MB alway narrowable: + NON_PRINTABLE = 0x02, + BACKSLASH = 0x04, + DBL_QUOTE = 0x08 + }; + + enum Flags + { + ROUNDTRIP = 0x01, + NON_ROUNDTRIP = 0x02, + ALLOW_WHITESPACE = 0x04 + }; + + cEncoder( int e, int f ); // mask of Encodings + virtual ~cEncoder(); + + void Encode( TSTRING& str ) const; + void Decode( TSTRING& str ) const; // TODO:BAM -- throw error! + + void ValidateSchema() const; + bool OnlyOneCatagoryPerChar() const; + bool AllIdentifiersUnique() const; + bool AllTestsRunOnEncodedString( const TSTRING& str ) const; + + private: + typedef std::vector< iCharEncoder* > sack_type; + + TSTRING Encode( TSTRING::const_iterator first, + TSTRING::const_iterator last, + sack_type::const_iterator encoding ) const; + + bool RoundTrip() const; + bool AllowWhiteSpace() const; + + sack_type m_encodings; + int m_fFlags; +}; + +// encodes ( BACKSLASH | DBL_QUOTE | NON_NARROWABLE | NON_PRINTABLE ) + +class cDisplayEncoder : public cEncoder +{ + public: + cDisplayEncoder( Flags f = NON_ROUNDTRIP ); + + void Encode( TSTRING& str ) const; + bool Decode( TSTRING& str ) const; + + static TSTRING EncodeInline( const TSTRING& sIn ) + { + TSTRING sOut = sIn; + cDisplayEncoder e; + e.Encode( sOut ); + return sOut; + } + + static TSTRING EncodeInlineAllowWS( const TSTRING& sIn ) + { + TSTRING sOut = sIn; + cDisplayEncoder e( (Flags)( NON_ROUNDTRIP | ALLOW_WHITESPACE ) ); + e.Encode( sOut ); + return sOut; + } +}; + + + +class cCharEncoderUtil +{ + public: + + static bool IsPrintable( TCHAR ch ); + static bool IsWhiteSpace( TCHAR ch ); + + static TSTRING CharStringToHexValue( const TSTRING& str ); + + static TSTRING HexValueToCharString( const TSTRING& str ); + + static TCHAR hex_to_char( TSTRING::const_iterator first, + TSTRING::const_iterator last ); + + static TSTRING char_to_hex( TCHAR ch ); + + static TSTRING DecodeHexToChar( TSTRING::const_iterator* pcur, + const TSTRING::const_iterator end ); + + + enum + { + BYTE_AS_HEX__IN_TCHARS = 2, + BYTES_PER_TCHAR = sizeof( TCHAR ), + TCHAR_AS_HEX__IN_TCHARS = BYTE_AS_HEX__IN_TCHARS * BYTES_PER_TCHAR + }; +}; + +#endif //__DISPLAYENCODER_H + + +/* +/////////////////////////////////////////////////////////////////////////////// +// displayencoder.h +// + +#ifndef __DISPLAYENCODER_H +#define __DISPLAYENCODER_H + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +/////////////////////////////////////////////// +// cDisplayEncoder +/////////////////////////////////////////////// + +template< class CharT > +class iCharEncoder_; + +// TODO:BAM -- i don't think that the order of encodings is important +// as long as AllIdentifiersUnique and OnlyOneCatagoryPerChar are true +template< class CharT > +class cEncoder +{ + public: + enum Encodings + { + NON_NARROWABLE = 0x01, // WC -> SB, SB alway narrowable: + NON_PRINTABLE = 0x02, + BACKSLASH = 0x04, + DBL_QUOTE = 0x08, + }; + + enum Flags + { + ROUNDTRIP = 0x01, + NON_ROUNDTRIP = 0x02, + }; + + cEncoder( int e, int f ); // mask of Encodings + virtual ~cEncoder(); + + void Encode( TSTRING& str ) const; + void Decode( TSTRING& str ) const; // TODO:BAM -- throw error! + + void ValidateSchema() const; + bool OnlyOneCatagoryPerChar() const; + bool AllIdentifiersUnique() const; + bool AllTestsRunOnEncodedString( const TSTRING& str ) const; + + private: + typedef std::vector< iCharEncoder_* > sack_type; + + sack_type m_encodings; + bool m_fRoundTrip; +}; + + +// encodes ( BACKSLASH | DBL_QUOTE | NON_NARROWABLE | NON_PRINTABLE ) +template< class CharT > +class cDisplayEncoder_ : public cEncoder< CharT > +{ + public: + cDisplayEncoder_( Flags f = NON_ROUNDTRIP ); + + void Encode( TSTRING& str ) const; + bool Decode( TSTRING& str ) const; +}; + + +/////////////////////////////////////////////// +// cTWLocale +/////////////////////////////////////////////// +// to make it easier to use.... +/////////////////////////////////////////////// +typedef cDisplayEncoder_ cDisplayEncoder; + + +#endif //__DISPLAYENCODER_H + +*/ + diff --git a/src/core/displayencoder_t.cpp b/src/core/displayencoder_t.cpp new file mode 100644 index 0000000..a1a0d78 --- /dev/null +++ b/src/core/displayencoder_t.cpp @@ -0,0 +1,367 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: displayencoder_t.cpp +// Date....: 10/18/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdcore.h" + +#ifdef TSS_TEST + +#include "test/utx.h" +#include "displayencoder.h" +#include "debug.h" +#include "twlocale.h" +#include "errorbucketimpl.h" + + +/////////////////////////////////////////////////////////////////////////////// +// UTIL +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _UNICODE + #define TSS_TCHAR_MIN WCHAR_MIN + #define TSS_TCHAR_MAX WCHAR_MAX +#else + #define TSS_TCHAR_MIN CHAR_MIN + #define TSS_TCHAR_MAX CHAR_MAX +#endif + +template< class CharT > bool IsPrintable( const std::basic_string< CharT >& str ) +{ + const std::ctype< CharT > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + for( std::basic_string< CharT >::const_iterator at = str.begin(); at != str.end(); at++ ) + { + if( ! ct.is( std::ctype_base::print, *at ) ) // if not printable + return false; + } + + return true; +} + +static void util_TestUnprintable( const TSTRING& strCUnprintable ) +{ + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + TSTRING strEncoded = strCUnprintable; + + e.Encode( strEncoded ); + TCOUT << strEncoded << std::endl; + TSTRING strOut = strEncoded; + e.Decode( strOut ); + + ASSERT( strOut == strCUnprintable ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// cDisplayEncoderTest +/////////////////////////////////////////////////////////////////////////////// +class cDisplayEncoderTest +{ +public: + + /////////////////////////////////////////////////////////////////////////// + // TestCharToHex + /////////////////////////////////////////////////////////////////////////// + void TestCharToHex( tss::TestContext& ctx ) + { + TCHAR ch; + TSTRING str; + const std::ctype< TCHAR > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + + // only use lowercase strings with this define + #define TSS_CHAR_TO_HEX_TEST( s ) \ + ch = 0x ## s; \ + str = cCharEncoderUtil::char_to_hex( ch ); \ + ct.tolower( str.begin(), str.end() ); \ + ASSERT( str == _T( #s ) ); + + TSS_CHAR_TO_HEX_TEST( fefe ); + TSS_CHAR_TO_HEX_TEST( 0000 ); + TSS_CHAR_TO_HEX_TEST( 1234 ); + TSS_CHAR_TO_HEX_TEST( ffff ); + TSS_CHAR_TO_HEX_TEST( 0001 ); + TSS_CHAR_TO_HEX_TEST( 543c ); + TSS_CHAR_TO_HEX_TEST( cccc ); + TSS_CHAR_TO_HEX_TEST( 9999 ); + TSS_CHAR_TO_HEX_TEST( abcd ); + } + + /////////////////////////////////////////////////////////////////////////// + // TestHexToChar + /////////////////////////////////////////////////////////////////////////// + void TestHexToChar( tss::TestContext& ctx ) + { + TCHAR ch; + TSTRING str; + + // only use lowercase strings with this define + #define TSS_HEX_TO_CHAR_TEST( s ) \ + str = _T( #s ); \ + ch = cCharEncoderUtil::hex_to_char( str.begin(), str.end() ); \ + ASSERT( ch == 0x ## s ); + + TSS_HEX_TO_CHAR_TEST( fefe ); + TSS_HEX_TO_CHAR_TEST( 0000 ); + TSS_HEX_TO_CHAR_TEST( 1234 ); + TSS_HEX_TO_CHAR_TEST( ffff ); + TSS_HEX_TO_CHAR_TEST( 0001 ); + TSS_HEX_TO_CHAR_TEST( 543c ); + TSS_HEX_TO_CHAR_TEST( cccc ); + TSS_HEX_TO_CHAR_TEST( 9999 ); + TSS_HEX_TO_CHAR_TEST( abcd ); + } + + ////////////////////////////////////////////////////////////////////////// + // TestStringToHex -- locale specific test -- only works in ASCII + /////////////////////////////////////////////////////////////////////////// + void TestStringToHex( tss::TestContext& ctx ) + { + TSTRING str; + const std::ctype< TCHAR > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + + // only use lowercase strings with this define + #define TSS_STRING_TO_HEX_TEST( s, n ) \ + str = cCharEncoderUtil::CharStringToHexValue( _T( #s ) ); \ + ct.tolower( str.begin(), str.end() ); \ + ASSERT( str == _T( #n ) ); + + TSS_STRING_TO_HEX_TEST( \n, 000a ); + TSS_STRING_TO_HEX_TEST( \r, 000d ); + TSS_STRING_TO_HEX_TEST( \r\n, 000d000a ); + TSS_STRING_TO_HEX_TEST( a\r\nb, 0061000d000a0062 ); + } + + ////////////////////////////////////////////////////////////////////////// + // TestHexToString -- locale specific test -- only works in Unicode + /////////////////////////////////////////////////////////////////////////// + void TestHexToString( tss::TestContext& ctx ) + { + TSTRING str; + const std::ctype< TCHAR > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + + // only use lowercase strings with this define + #define TSS_HEX_TO_STRING_TEST( s, n ) \ + str = cCharEncoderUtil::HexValueToCharString( _T( #n ) ); \ + ct.tolower( str.begin(), str.end() ); \ + ASSERT( str == _T( #s ) ); + + TSS_HEX_TO_STRING_TEST( \n, 000a ); + TSS_HEX_TO_STRING_TEST( \r, 000d ); + TSS_HEX_TO_STRING_TEST( \r\n, 000d000a ); + TSS_HEX_TO_STRING_TEST( a\r\nb, 0061000d000a0062 ); + } + + ////////////////////////////////////////////////////////////////////////// + // TestUnconvertable -- locale specific test -- only works in Unicode + /////////////////////////////////////////////////////////////////////////// + void TestUnconvertable( tss::TestContext& ctx ) + { + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + const std::ctype< TCHAR > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + TSTRING str; + TCHAR ch; + + // only use lowercase strings with this define + #define TSS_UNCONVERTABLE_TEST( n ) \ + ch = 0x ## n; \ + str = ch; \ + e.Encode( str ); \ + ct.tolower( str.begin(), str.end() ); \ + ASSERT( str == _T("\\x") _T( #n ) _T("x") ); + + TSS_UNCONVERTABLE_TEST( fefe ); + TSS_UNCONVERTABLE_TEST( 1234 ); + TSS_UNCONVERTABLE_TEST( ffff ); + TSS_UNCONVERTABLE_TEST( 1000 ); + TSS_UNCONVERTABLE_TEST( 543c ); + TSS_UNCONVERTABLE_TEST( cccc ); + TSS_UNCONVERTABLE_TEST( 9999 ); + TSS_UNCONVERTABLE_TEST( 0123 ); + TSS_UNCONVERTABLE_TEST( 0100 ); + } + + ////////////////////////////////////////////////////////////////////////// + // TestUnprintable -- locale specific test -- only works in Unicode + /////////////////////////////////////////////////////////////////////////// + void TestUnprintable( tss::TestContext& ctx ) + { + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + const std::ctype< TCHAR > *pct = 0, &ct = tss::GetFacet( std::locale(), pct ); + TSTRING str; + TCHAR ch; + + // only use lowercase strings with this define + #define TSS_UNPRINTABLE_TEST( n ) \ + ch = 0x ## n; \ + str = ch; \ + e.Encode( str ); \ + ct.tolower( str.begin(), str.end() ); \ + ASSERT( str == _T("\\x") _T( #n ) _T("x") ); + + TSS_UNPRINTABLE_TEST( 000a ); + TSS_UNPRINTABLE_TEST( 000d ); + } + + ////////////////////////////////////////////////////////////////////////// + // TestQuoteAndBackSlash + /////////////////////////////////////////////////////////////////////////// + void TestQuoteAndBackSlash( tss::TestContext& ctx ) + { + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + TSTRING str; + + str = _T("\\"); + e.Encode( str ); + ASSERT( str == _T("\\\\") ); + + str = _T("\""); + e.Encode( str ); + ASSERT( str == _T("\\\"") ); + } + + // TODO:BAM -- try multibyte now..... + + + /////////////////////////////////////////////////////////////////////////// + // Basic + /////////////////////////////////////////////////////////////////////////// + void Basic( tss::TestContext& ctx ) + { + try + { + //============================================================= + // TEST UNPRINTABLE ENCODING/ROUNDTRIP + //============================================================= + + util_TestUnprintable( _T("normal string") ); + + util_TestUnprintable( _T("return\n") ); + util_TestUnprintable( _T("ret\rurn\n") ); + util_TestUnprintable( _T("ret\rnurn\n") ); + + util_TestUnprintable( _T("bell\x08") ); + util_TestUnprintable( _T("\x08 bell") ); + util_TestUnprintable( _T("be\x08ll") ); + + util_TestUnprintable( _T("\x1F\x1F\x1F") ); + + util_TestUnprintable( _T("big\xFF") ); + util_TestUnprintable( _T("\xEE big") ); + util_TestUnprintable( _T("\xEE\xEEtwo big") ); + util_TestUnprintable( _T("small\x01") ); + util_TestUnprintable( _T("\x01\x01two small") ); + + //============================================================= + // TEST UNCONVERTABLE CHARS + //============================================================= + TSTRING strMessWithMe = _T("Mess with me..."); + for( size_t c = TSS_TCHAR_MIN; + c < TSS_TCHAR_MAX; +#ifdef _UNICODE + c += ( TSS_TCHAR_MAX / 150 ) ) +#else + c++ ) +#endif + { + if( ( c != '\0' ) ) + { + strMessWithMe += c; + } + } + util_TestUnprintable( strMessWithMe ); + + //============================================================= + // TEST \\ and \x ENCODING/ROUNDTRIP + //============================================================= + + util_TestUnprintable( _T("\\Other \\\\slashes") ); + util_TestUnprintable( _T("\\Other slashes\\\\") ); + util_TestUnprintable( _T("O\\ther slashes\\\\") ); + util_TestUnprintable( _T("\\\\\\") ); + + util_TestUnprintable( _T("\\xTricky") ); + util_TestUnprintable( _T("Tri\\xcky") ); + util_TestUnprintable( _T("Tricky\\x") ); + util_TestUnprintable( _T("\\Tricky\\\\x") ); + + + //============================================================= + // TEST UNCONVERTABLE, UNPRINTABLE, AND \\ and \" CHARS + //============================================================= + TSTRING strMessWithMe2 = _T("Mess with me..."); + for( size_t ch = TSS_TCHAR_MIN; + ch < TSS_TCHAR_MAX; +#ifdef _UNICODE + ch += ( TSS_TCHAR_MAX / 150 ) ) +#else + ch++ ) +#endif + { + if( ( ch != '\0' ) ) + { + strMessWithMe2 += ch; + } + } + + strMessWithMe2 += _T("\r\n\t\b\\\"\\\\\\\"\v\""); + util_TestUnprintable( strMessWithMe2 ); + + // TODO:BAM -- create multibyte tests (create a mb string at random, then test it. + // make sure there are '\' and '"' in it ) + } + catch( eError& e ) + { + cErrorReporter::PrintErrorMsg( e ); + ASSERT(false); + } + } +}; + +TSS_BeginTestSuiteFrom( cDisplayEncoderTest ) + + TSS_AddTestCase( Basic ); + TSS_AddTestCase( TestHexToChar ); + TSS_AddTestCase( TestCharToHex ); + TSS_AddTestCase( TestStringToHex ); + TSS_AddTestCase( TestHexToString ); + TSS_AddTestCase( TestUnconvertable ); + TSS_AddTestCase( TestUnprintable ); + TSS_AddTestCase( TestQuoteAndBackSlash ); + +TSS_EndTestSuite( cDisplayEncoderTest ) + +#endif // TSS_TEST + +// eof: displayencoder_t.cpp diff --git a/src/core/displayutil.cpp b/src/core/displayutil.cpp new file mode 100644 index 0000000..aa45571 --- /dev/null +++ b/src/core/displayutil.cpp @@ -0,0 +1,100 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: displayutil.cpp +// Date....: 7/12/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdcore.h" +#include "displayutil.h" +#include "ntmbs.h" +#include + +TSTRING cDisplayUtil::FormatMultiLineString( const TSTRING& str, int nOffset, int nWidth ) +{ + TOSTRINGSTREAM sstr; + TSTRING strT; + bool fFirstLine = true; + for( TSTRING::const_iterator i = str.begin(); i != str.end(); i = *i ? i + 1 : i ) + { + // return found -- add line to output string + if( _T('\n') == *i ) + { + // only do offset for strings after the first + if( fFirstLine ) + { + fFirstLine = false; + } + else + { + // add offset + for( int j = 0; j < nOffset; j++ ) + sstr << _T(" "); + + // set width + sstr << std::setw( nWidth ); + } + + // add to stringstream + sstr << strT << std::endl; + + // erase temp string + strT.erase(); + } + else + { + // add char to string + strT.append( i, (TSTRING::const_iterator)(*i ? i + 1 : i) ); + } + } + + // add last portion -- no endl + // we want our client to be able to say "out << PropAsString() << endl;" + + // add offset + if( ! fFirstLine ) + { + for( int j = 0; j < nOffset; j++ ) + sstr << _T(" "); + } + + // set width + sstr << std::setw( nWidth ); + + // now add last string + sstr << strT; + + return( sstr.str() ); +} + +// eof: displayutil.cpp diff --git a/src/core/displayutil.h b/src/core/displayutil.h new file mode 100644 index 0000000..e9ab6a6 --- /dev/null +++ b/src/core/displayutil.h @@ -0,0 +1,101 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: displayutil.h +// Date....: 7/12/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#ifndef __DISPLAYUTIL_H +#define __DISPLAYUTIL_H + +class cDisplayUtil +{ +public: + static TSTRING FormatMultiLineString( const TSTRING& str, int nOffset, int nWidth ); +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Way too verbose here, but it was the best I could do. I know, I know. +// If it's too complicated to explain, there's an easier way to do it. +// Soooo, I'll just put a TODO:BAM here +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// +// So, there's this problem with outputting a string with newlines in it when you want +// to format the output stream. For instance: +// +// TCHAR szTenSpaceMargin[] = { _T(" ") }; +// TCHAR szMessage[] = { _T("First Line\nSecond Line\n") }; +// +// TCOUT << szTenSpaceMargin << setw(15) << szMessage; +// +// What happens is that you get output like: +// " First Line" +// ^ ^^ ^ +// |--10 sp-||---15 width--| +// "Second Line" +// ^ +// | 0 sp, 0 width +// +// When you really wanted: +// " First Line" +// ^ ^^ ^ +// |--10 sp-||---15 width--| +// " Second Line" +// ^ ^^ ^ +// |--10 sp-||---15 width--| +// +// +// Sooooo, what this little beauty does is change the string +// "First Line\nSecond Line\n" into ""First Line\n Second Line\n" +// ( adds nOffset spaces after each '\n', and makes sure that each line is +// in a output width specified by nWidth ) +// +// So you can output a multiline string and have each line be formatted +// like the first one was. +// +// So, for the preceeding example, +// +// change: +// TCOUT << szTenSpaceMargin << setw(15) << szMessage; +// +// to: +// TCOUT << szTenSpaceMargin << setw(15) +// << cDisplayUtil::FormatMultiLineString( szMessage, 10, 15 ); +// +// Comprende? It's crazy but it works. +// +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#endif // #ifndef __DISPLAYUTIL_H + diff --git a/src/core/error.cpp b/src/core/error.cpp new file mode 100644 index 0000000..8bd6887 --- /dev/null +++ b/src/core/error.cpp @@ -0,0 +1,51 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// error.cpp +// +#include "stdcore.h" +#include "error.h" +#include "crc32.h" + +/////////////////////////////////////////////////////////////////////////////// +// CalcHash +/////////////////////////////////////////////////////////////////////////////// +uint32 eError::CalcHash( const char* name ) +{ + CRC_INFO crc; + crcInit( crc ); + crcUpdate( crc, (const uint8*)name, strlen( name ) ); + crcFinit( crc ); + return crc.crc; +} + + diff --git a/src/core/error.h b/src/core/error.h new file mode 100644 index 0000000..cc8d197 --- /dev/null +++ b/src/core/error.h @@ -0,0 +1,303 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// error.h +// +#ifndef __ERROR_H +#define __ERROR_H + + +//----------------------------------------------------------------------------- +// eError +//----------------------------------------------------------------------------- +class eError +{ +public: + + //------------------------------------------------------------------------- + // Construction and Assignment + //------------------------------------------------------------------------- + eError( const TSTRING& msg, uint32 flags = 0 ); + explicit eError( const eError& rhs ); + explicit eError(); + void operator=( const eError& rhs ); + + //------------------------------------------------------------------------- + // Destruction + //------------------------------------------------------------------------- + virtual ~eError(); + + //------------------------------------------------------------------------- + // Data Access + //------------------------------------------------------------------------- + virtual uint32 GetID() const = 0; + // returns a system wide unique identifier for this exception. See the + // macro below for the typical implementation of this method. + // This is used to associate the error with a string description of the + // error via the global error table. + + virtual TSTRING GetMsg() const; + // returns specific information about the error that occured. Provides + // additional information about the error described by GetID(). It should + // not provide any information redundant with GetID(). + // + // The string passed to the constructor should be formated properly to + // be displayed as the "Second" part of an error message, or the derived + // class should override GetMsg() and return a string appropriate for display. + + uint32 GetFlags() const; + // Flags are defined below. Currently, these only have an impact on how errors are + // displayed. + + //------------------------------------------------------------------------- + // Flags + //------------------------------------------------------------------------- + enum Flag + { + NON_FATAL = 0x00000001, // displays "Error" or "Warning" ? + SUPRESS_THIRD_MSG = 0x00000002 // supresses the "continuing" or "exiting" message + }; + + void SetFlags( uint32 flags ); + + //------------------------------------------------------------------------- + // Flag Convenience Methods + //------------------------------------------------------------------------- + void SetFatality(bool fatal); + bool IsFatal() const; + // Fatality is set to true by default when eError is constructed. But when an error + // it is put in an cErrorBucket chain it the code doing so may wish to set the fatality + // to non-fatal to indicate that the error is actually a warning and program flow + // is going to continue. + void SetSupressThird(bool supressThird); + bool SupressThird() const; + + //------------------------------------------------------------------------- + // Utility Methods + //------------------------------------------------------------------------- + static uint32 CalcHash( const char* name ); + // calculates the CRC32 of the string passed in as name. This methods + // asserts that name is non null. This is used to generate unique IDs + // for errors. + + //------------------------------------------------------------------------- + // Private Implementation + //------------------------------------------------------------------------- +protected: + TSTRING mMsg; + uint32 mFlags; +}; + +//----------------------------------------------------------------------------- +// Error Related Macros +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// TSS_BEGIN_EXCEPTION / TSS_END_EXCEPTION +// +// Serves the same purpose as TSS_EXCEPTION but allows custom data and methods +// to be added to the exception class. +/////////////////////////////////////////////////////////////////////////////// + +#if HAVE_GCC +#define TSS_BEGIN_EXCEPTION_EXPLICIT +#else +#define TSS_BEGIN_EXCEPTION_EXPLICIT explicit +#endif + +#define TSS_BEGIN_EXCEPTION( except, base ) \ + class except : public base \ + {\ + public:\ + except( const TSTRING& msg, uint32 flags = 0 ) \ + : base( msg, flags ) {} \ + TSS_BEGIN_EXCEPTION_EXPLICIT except( const except& rhs ) \ + : base( rhs ) {} \ + explicit except() : base() {} \ + \ + virtual uint32 GetID() const \ + {\ + return CalcHash( #except ); \ + }\ + +#define TSS_END_EXCEPTION( ) \ + }; + +/////////////////////////////////////////////////////////////////////////////// +// TSS_BEGIN_EXCEPTION_NO_CTOR +// +// Same as TSS_BEGIN_EXCEPTION, but doesn't define any ctors. +/////////////////////////////////////////////////////////////////////////////// +#define TSS_BEGIN_EXCEPTION_NO_CTOR( except, base ) \ + class except : public base \ + {\ + public:\ + explicit except() : base() {} \ + \ + virtual uint32 GetID() const \ + {\ + return CalcHash( #except ); \ + }\ + +/////////////////////////////////////////////////////////////////////////////// +// TSS_EXCEPTION +// +// This is a convenience define for quickly defining an exception class. After +// defining a new exception, don't forget to add it to the package's error +// string file! +// +// TODO (mdb) -- do we want to cache the CRC? if we store it in a class static +// variable, then we will need to define it in the cpp file as well ... +/////////////////////////////////////////////////////////////////////////////// +#define TSS_EXCEPTION( except, base ) \ + TSS_BEGIN_EXCEPTION( except, base ) \ + TSS_END_EXCEPTION() + +//----------------------------------------------------------------------------- +// Inline Implementation +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// eError +/////////////////////////////////////////////////////////////////////////////// +inline eError::eError( const TSTRING& msg, uint32 flags ) +: mMsg ( msg ), + mFlags ( flags ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// eError +/////////////////////////////////////////////////////////////////////////////// +inline eError::eError( const eError& rhs ) +: mMsg ( rhs.mMsg ), + mFlags ( rhs.mFlags ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// eError +/////////////////////////////////////////////////////////////////////////////// +inline eError::eError( ) +: mMsg ( _T("") ), + mFlags ( 0 ) +{ + +} + + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +inline void eError::operator=( const eError& rhs ) +{ + mMsg = rhs.mMsg; + mFlags = rhs.mFlags; +} + +/////////////////////////////////////////////////////////////////////////////// +// ~eError +/////////////////////////////////////////////////////////////////////////////// +inline eError::~eError() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// GetMsg +/////////////////////////////////////////////////////////////////////////////// +inline TSTRING eError::GetMsg() const +{ + return mMsg; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFlags +/////////////////////////////////////////////////////////////////////////////// +inline uint32 eError::GetFlags() const +{ + return mFlags; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetFlags +/////////////////////////////////////////////////////////////////////////////// +inline void eError::SetFlags( uint32 flags ) +{ + mFlags = flags; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetFatality +/////////////////////////////////////////////////////////////////////////////// +inline void eError::SetFatality(bool fatal) +{ + if (fatal) + mFlags &= ~(uint32)NON_FATAL; + else + mFlags |= (uint32)NON_FATAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// IsFatal +/////////////////////////////////////////////////////////////////////////////// +inline bool eError::IsFatal() const +{ + return (mFlags & (uint32)NON_FATAL) == 0; + +} + +/////////////////////////////////////////////////////////////////////////////// +// SetSupressThird +/////////////////////////////////////////////////////////////////////////////// +inline void eError::SetSupressThird(bool supressThird) +{ + if (supressThird) + mFlags |= (uint32)SUPRESS_THIRD_MSG; + else + mFlags &= ~(uint32)SUPRESS_THIRD_MSG; +} + +/////////////////////////////////////////////////////////////////////////////// +// SupressThird +/////////////////////////////////////////////////////////////////////////////// +inline bool eError::SupressThird() const +{ + return (mFlags & (uint32)SUPRESS_THIRD_MSG) == 0; +} + + + +#endif //__ERROR_H + diff --git a/src/core/error_t.cpp b/src/core/error_t.cpp new file mode 100644 index 0000000..e9b25ac --- /dev/null +++ b/src/core/error_t.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// error_t.h -- the vcc exception test driver + +#include "stdcore.h" +#include "error.h" +#include "test/test.h" +#include + +void TestError() +{ +//#pragma message( __FILE__ "(1) : TODO - implement this test file") + +/* + try + { + std::cout << "Before Exception" << std::endl; + std::cout << "Line number before throw: " << __LINE__ << std::endl; + THROW_ERROR(53, _T("This is an error!")); + std::cout << "After Exception" << std::endl; + } + catch(eError& e) + { + TEST(e.GetErrorNum() == 53); + TEST(_tcscmp(e.GetMsg().c_str(), _T("This is an error!")) == 0); + TCOUT << _T("Exception caught!\n\tErrorNum=") << e.GetErrorNum() << _T("\n\t") << e.GetMsg() << std::endl; + } + + try + { + THROW_INTERNAL("error_t.cpp"); + } + catch(eInternal& e) + { + TEST(e.GetErrorNum() == eInternal::ERR_INTERNAL); + TCOUT << _T("Internal error caught!\n\tErrorNum=") << e.GetErrorNum() << _T("\n\t") << e.GetMsg() << std::endl; + } + catch(...) + { + TEST(false); + } +*/ +} diff --git a/src/core/errorbucket.h b/src/core/errorbucket.h new file mode 100644 index 0000000..12e752a --- /dev/null +++ b/src/core/errorbucket.h @@ -0,0 +1,102 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// errorbucket.h +// + +#ifndef __ERRORBUCKET_H +#define __ERRORBUCKET_H + +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +class eError; + +/////////////////////////////////////////////////////////////////////////////// +// cErrorBucket -- contains an interface that handles error reporting, and +// contains a link to a child bucket. Each concrete implementation of the +// cErrorBucket interface will perform its own specific task related to the +// error's occurence (print to stderr, store in a queue, etc) and then forward +// the error on to its child link. The parent bucket does not own the destruction +// of the pointer to the child bucket. +/////////////////////////////////////////////////////////////////////////////// +class cErrorBucket +{ +public: + cErrorBucket(); + virtual ~cErrorBucket() {} + + virtual void AddError(const eError& error); + // add an error to the bucket + + cErrorBucket* GetChild(); + // returns the bucket that the current bucket is chained to, or + // NULL if nothing is attached to it. + cErrorBucket* SetChild(cErrorBucket* pNewChild); + // sets the child link of this bucket; returns the old link value + +protected: + virtual void HandleError(const eError& error) = 0; + // override this to implement error handling functionality specific to + // the derived class + cErrorBucket* mpChild; +}; + +//############################################################################# +// inline implementation + +/////////////////// +// cErrorBucket +/////////////////// +inline cErrorBucket::cErrorBucket() : + mpChild(0) +{ +} + +inline cErrorBucket* cErrorBucket::GetChild() +{ + return mpChild; +} + +inline cErrorBucket* cErrorBucket::SetChild(cErrorBucket* pNewChild) +{ + cErrorBucket* pOldChild = mpChild; + mpChild = pNewChild; + return pOldChild; +} + +#endif + diff --git a/src/core/errorbucketimpl.cpp b/src/core/errorbucketimpl.cpp new file mode 100644 index 0000000..132b3f1 --- /dev/null +++ b/src/core/errorbucketimpl.cpp @@ -0,0 +1,307 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// errorbucketimpl.cpp +#include "stdcore.h" +#include "errorbucketimpl.h" +#include "errortable.h" +#include "serializer.h" +#include "corestrings.h" +#include "displayencoder.h" + +//############################################################################# +// cErrorBucket +//############################################################################# +void cErrorBucket::AddError(const eError& error) +{ + HandleError(error); + if(mpChild) + mpChild->AddError(error); +} + +//############################################################################# +// cErrorReporter +//############################################################################# +void cErrorReporter::PrintErrorMsg(const eError& error, const TSTRING& strExtra) +{ + cDisplayEncoder e( + (cDisplayEncoder::Flags) ( cDisplayEncoder::NON_ROUNDTRIP | + cDisplayEncoder::ALLOW_WHITESPACE ) ); + TSTRING errStr; + int len; + + // + // if the ID is zero, just return. + // this should only occur at the top level of a program (ie -- twcmdline.cpp) and + // indicates that an error occurred and an error message has already been printed out. + // Therefore, we will do nothing here but return. + // + + // TODO: Having an error with an ID of 0 is legacy. The only place it happens at this + // point is when we throw ePoly() with no constructor arguments. At some point we want + // to stop using the mechanism have non-printing errors, thus we leave in the ASSERT below. + // But we don't want to break any release code, thus we return on the next line - June 2, 1999 DMB. + ASSERT( error.GetID() != 0 ); + + if( error.GetID() == 0 ) + return; + + // "First Part" header + errStr = TSS_GetString( cCore, error.IsFatal() ? core::STR_ERROR_ERROR + : core::STR_ERROR_WARNING ); + + if (errStr.empty()) + { + TOSTRINGSTREAM strm; + ASSERT( sizeof( uint32 ) == sizeof(unsigned int) ); // for cast on next line + strm << _T("Unknown Error ID ") << (unsigned int)error.GetID(); + errStr = strm.str(); + } + + len = errStr.length(); // save for later + TCERR << errStr; + + // "First Part" error string + TSTRING prependToSecond; + +// #pragma message("errorbucketimpl.cpp needs a little help in the mb arena, with the findfirst/last and such") + + errStr = cErrorTable::GetInstance()->Get( error.GetID() ); + if(! errStr.empty()) + { + // If the first part has a '\n' in it, we take everything following and prepend it to the + // second part. This was added to allow specifing a verbose string as the second part + // of an error message when building the error table. This change was made on July 27, 1999 + TSTRING::size_type firstLF; + if ((firstLF = errStr.find_first_of(_T('\n'))) != TSTRING::npos) + { + prependToSecond = errStr.substr(firstLF + 1); // don't include '\n' in new string + errStr.erase(firstLF); + } + + ASSERT(errStr.length() + len + 6 < 80); // line too big for terminal? + // Add 6 to account for "### ' and ': ' + TCERR << TSS_GetString( cCore, core::STR_ERROR_COLON ) << _T(" ") << errStr; + TCERR << std::endl; + } + + // "Second Part" error string + const int WIDTH = 80 - 4; // allow for "### " prefix to every error line + const TCHAR SPACE = _T(' '); + + errStr = prependToSecond + error.GetMsg() + strExtra; + e.Encode( errStr ); + if (! errStr.empty()) + { + do + { + // look for newline chars + TSTRING::size_type firstNewLine; + TSTRING currentStr = errStr.substr(0, (firstNewLine = errStr.find_first_of(_T('\n')))); + errStr.erase(0, (firstNewLine < errStr.length() ? firstNewLine + 1 : firstNewLine)); + + // break up the error string in case it is larger than screen width + do + { + if (currentStr.length() <= (unsigned int)WIDTH) + { + TCERR << TSS_GetString( cCore, core::STR_ERROR_HEADER ) << currentStr << std::endl; + break; + } + + TSTRING::size_type lastSpace = currentStr.find_last_of(SPACE, currentStr.length() >= WIDTH - 1 ? WIDTH - 1 : TSTRING::npos); + if (lastSpace == TSTRING::npos) + { + // can't find space to break at so this string will just have to be longer than screen width. + // search forward for a space so we break at the next even word boundry. + lastSpace = currentStr.find_first_of(SPACE, 0); + if (lastSpace == TSTRING::npos) + // Well, there is no space before the end of the string. + // So print the whole string out. + lastSpace = currentStr.length(); + } + + TCERR << TSS_GetString( cCore, core::STR_ERROR_HEADER ) + << currentStr.substr( 0, lastSpace ) + << std::endl; + + currentStr.erase( 0, lastSpace + 1 ); + } + while ( !currentStr.empty() ); + } + while ( !errStr.empty() ); + } + + // "Third Part" print 'exiting' or 'continuing' + // note that we supress this part if the appropriate flag is set... + // + if( (error.GetFlags() & eError::SUPRESS_THIRD_MSG) == 0 ) + { + TCERR << TSS_GetString( cCore, core::STR_ERROR_HEADER) + << TSS_GetString( + cCore, + error.IsFatal() + ? core::STR_ERROR_EXITING + : core::STR_ERROR_CONTINUING ) << std::endl; + } +} + +void cErrorReporter::HandleError(const eError& error) +{ + PrintErrorMsg(error); +} + +//############################################################################# +// cErrorTracer +//############################################################################# +void cErrorTracer::HandleError(const eError& error) +{ + cDebug d("cErrorTracer::HandleError"); + + d.TraceError( _T("%s : %s\n"), + cErrorTable::GetInstance()->Get( error.GetID() ).c_str(), + error.GetMsg().c_str() ); +} + +//############################################################################# +// cErrorQueue +//############################################################################# +IMPLEMENT_TYPEDSERIALIZABLE(cErrorQueue, _T("cErrorQueue"), 0, 1); + +void cErrorQueue::Clear() +{ + mList.clear(); +} + +int cErrorQueue::GetNumErrors() const +{ + return mList.size(); +} + +void cErrorQueue::HandleError(const eError& error) +{ + mList.push_back( ePoly( error ) ); +} + +cErrorQueueIter::cErrorQueueIter(cErrorQueue& queue) : + mList(queue.mList) +{ + SeekBegin(); +} + +cErrorQueueIter::cErrorQueueIter(const cErrorQueue& queue) +: mList( ((cErrorQueue*)&queue)->mList ) +{ + SeekBegin(); +} + + +void cErrorQueueIter::SeekBegin() +{ + mIter = mList.begin(); +} + +void cErrorQueueIter::Next() +{ + ++mIter; +} + +bool cErrorQueueIter::Done() const +{ + return (mIter == mList.end()); +} + +const ePoly& cErrorQueueIter::GetError() const +{ + ASSERT(! Done()); + return (*mIter); +} + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void cErrorQueue::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("ErrorQueue Read"))); + + int32 size; + mList.clear(); + pSerializer->ReadInt32(size); + for(int i = 0; i < size; ++i) + { + int32 errorNumber; + TSTRING errorString; + int32 flags; + + pSerializer->ReadInt32 (errorNumber); + pSerializer->ReadString (errorString); + pSerializer->ReadInt32 (flags); + + mList.push_back( ePoly( errorNumber, errorString, flags ) ); + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void cErrorQueue::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(mList.size()); + ListType::const_iterator i; + for( i = mList.begin(); i != mList.end(); ++i) + { + pSerializer->WriteInt32 ((*i).GetID()); + pSerializer->WriteString((*i).GetMsg()); + pSerializer->WriteInt32 ((*i).GetFlags()); + } + +} + + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cErrorQueue::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFCOErrorQueue::TraceContents"); + ListType::const_iterator i; + int counter = 0; + for(i = mList.begin(); i != mList.end(); i++, counter++) + { + d.Trace(dl, _T("Error[%d]: num = %x string = %s\n") , counter, (*i).GetID(), (*i).GetMsg().c_str()); + } +} + diff --git a/src/core/errorbucketimpl.h b/src/core/errorbucketimpl.h new file mode 100644 index 0000000..45d23e5 --- /dev/null +++ b/src/core/errorbucketimpl.h @@ -0,0 +1,174 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// errorbucketimpl.h +// +// This component contains classes derived from cErrorBucket and helper classes. +// They were broken out of errorbucket.h becuase many components will only need to +// know about cErrorBucket, so we reduce system dependencies by keeping these classes +// separate. +#ifndef __ERRORBUCKETIMPL_H +#define __ERRORBUCKETIMPL_H + +#ifndef __ERRORBUCKET_H +#include "errorbucket.h" +#endif + +#ifndef __DEBUG_H +#include "debug.h" +#endif + +#ifndef __ERROR_H +#include "error.h" +#endif + +#ifndef __ERRORUTIL_H +#include "errorutil.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +////////////////////////////////////////////////////// +// cErrorReporter -- sends all error messages to +// stderr +////////////////////////////////////////////////////// +class cErrorReporter : public cErrorBucket +{ +public: + static void PrintErrorMsg(const eError& error, const TSTRING& strExtra = _T("")); + // function that HandleError() uses to print the error messages to stderr. + // this function uses the current authoritative format for error reporting, so + // other functions needing to display errors to the user should use this. + // + + // NOTE:bam 5/7/99 -- I don't think the below is true anymore? + // NOTE:mdb -- if the error has an ID of zero, nothing will be printed. This + // is a way to throw a fatal error where the error reporting has already + // occurred. + +protected: + virtual void HandleError(const eError& error); +}; + +/////////////////////////////////////////////////////// +// cErrorTracer -- traces all errors with the D_ERROR debug +// level +/////////////////////////////////////////////////////// +class cErrorTracer : public cErrorBucket +{ +protected: + virtual void HandleError(const eError& error); +}; + + +////////////////////////////////////////////////////// +// cErrorQueue -- keeps track of all the errors that +// are reported to it, providing an interface for +// retrieving them at a later time +////////////////////////////////////////////////////// +class cErrorQueue : public cErrorBucket, public iTypedSerializable +{ + friend class cErrorQueueIter; +public: + void Clear(); + // remove all errors from the queue + int GetNumErrors() const; + // returns how many errors are in the queue + + // + // iSerializable interface + // + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + // + // Debugging + // + void TraceContents(int dl = -1) const; + +protected: + virtual void HandleError(const eError& error); +private: + typedef std::list ListType; + ListType mList; + + DECLARE_TYPEDSERIALIZABLE() +}; + +class cErrorQueueIter +{ +public: + cErrorQueueIter(cErrorQueue& queue); + cErrorQueueIter(const cErrorQueue& queue); + ~cErrorQueueIter() {} + + // iteration methods + void SeekBegin(); + void Next(); + bool Done() const; + + // access to the error + const ePoly& GetError() const; + // both of these return results are undefined if the iterator + // is not valid (ie - IsDone() == true) +private: + cErrorQueue::ListType& mList; + cErrorQueue::ListType::iterator mIter; +}; + +////////////////////////////////////////////////////// +// cErrorBucketNull -- an error bucket that plays the +// role of /dev/null +////////////////////////////////////////////////////// +class cErrorBucketNull : public cErrorBucket +{ + virtual void AddError(const eError& ) {} +protected: + virtual void HandleError(const eError& ) {} +}; + +////////////////////////////////////////////////////// +// cErrorBucketPassThru -- does nothing with errors; +// just passes them on to its children +////////////////////////////////////////////////////// +class cErrorBucketPassThru : public cErrorBucket +{ +protected: + virtual void HandleError(const eError& ) {} +}; + + + +#endif + diff --git a/src/core/errorbucketimpl_t.cpp b/src/core/errorbucketimpl_t.cpp new file mode 100644 index 0000000..7a9bfa5 --- /dev/null +++ b/src/core/errorbucketimpl_t.cpp @@ -0,0 +1,142 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// errorbucketimpl_t.cpp + +#include "stdcore.h" +#include "errorbucketimpl.h" +#include "test/test.h" +#include "debug.h" +#include "archive.h" +#include "errorgeneral.h" + +// test option 7 +void TestErrorBucketImpl() +{ +/* + //This whole function is in sorry shape... TODO: Fix this DRA + d.TraceDebug("Entering...\n"); + + cErrorReporter er; + cErrorQueue eq; + + er.SetChild(&eq); + + +//These calls to PrintErrorMsg are broken. The code is probably old. -DRA + + // Test error reporting + cErrorReporter::PrintErrorMsg(eError(_T("This should have a single line."))); + cErrorReporter::PrintErrorMsg(eError(_T("This should have a mulitiple lines since I have") + _T(" put so much text here. But it does have a lot") + _T(" of spaces so cErrorReporter should have no") + _T(" problem breaking it up.") + )); + cErrorReporter::PrintErrorMsg(eError(_T("This has many long words: ") + _T("40chars_________________________________") + _T(" short words ") + _T("50chars___________________________________________") + _T(" short words ") + _T("90chars___________________________________________________________________________________") + _T(" short words short words short words short words ") + _T("90chars___________________________________________________________________________________") + )); + cErrorReporter::PrintErrorMsg(eError(_T("The error reporter should handle newlines.\n") + _T("Newlines should break up the text appropriately. Who knows when they will occur. Can't have them getting in the way.\n") + _T("And one last line with a big char strings: 90chars___________________________________________________________________________________ 40chars_________________________________ 50chars___________________________________________") + )); + + + // TODO -- test the error table + // TODO -- test the error filter + // set some errors... + TSS_EXCEPTION( eTestErrorBucketImpl, eError ); + eTestErrorBucketImpl error1(_T("Error A")), error2(_T("Error B")), error3(_T("Error C")); + + er.AddError(error1); d.TraceDebug("Adding error 0 -- Error A\n"); + er.AddError(error2); d.TraceDebug("Adding error 1 -- Error B\n"); + er.AddError(error3); d.TraceDebug("Adding error 100 -- Error C\n"); + + // those should have gone out to stderr; let's check the queue + cErrorQueueIter i(eq); + int counter = 0; + for(i.SeekBegin(); ! i.Done(); i.Next(), counter++) + { + switch(counter) + { + case 0: + TEST(i.GetError().GetID() == error1.GetID()); + TEST(i.GetError().GetMsg().compare(_T("Error A")) == 0); + break; + case 1: + TEST(i.GetError().GetID() == error2.GetID()); + TEST(i.GetError().GetMsg().compare(_T("Error B")) == 0); + break; + case 2: + TEST(i.GetError().GetID() == error3.GetID()); + TEST(i.GetError().GetMsg().compare(_T("Error C")) == 0); + break; + default: + TEST(false); + } + } + + TODO - test this stuff that's commented out + + TCOUT << _T("Following string should be a cArchive::ERR_OPEN_FAILED error:\n"); + TCOUT << cErrorTable::GetErrorString(cArchive::ERR_OPEN_FAILED) << std::endl; + +// print out all error strings +#if 1 + // Look up all errors. + // Note: our current error printing format limits us to 4 digit errors, so this should work for a while. + int errornum; + for (errornum = 0; errornum <= 9999; ++errornum) + { + TSTRING errorString = cErrorTable::GetErrorString(errornum); + if (errorString.compare(0, 26, _T("**** Invalid Error Number ")) != 0) + { + TCOUT << _T("### Error "); + + TCOUT.width(4); + TCHAR oldfill = TCOUT.fill(_T('0')); + TCOUT << errornum; + TCOUT.fill(oldfill); + + TCOUT << _T(": ") << errorString << std::endl; + } + } +#endif + + d.TraceDebug("Leaving...\n"); +*/ +} + diff --git a/src/core/errorgeneral.h b/src/core/errorgeneral.h new file mode 100644 index 0000000..c78b285 --- /dev/null +++ b/src/core/errorgeneral.h @@ -0,0 +1,49 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// errorgeneral.h -- +// + +#ifndef __ERRORGENERAL_H +#define __ERRORGENERAL_H + +#include "error.h" + +TSS_EXCEPTION( eErrorGeneral, eError ); +TSS_EXCEPTION( eOpen, eErrorGeneral ); +TSS_EXCEPTION( eOpenRead, eErrorGeneral ); +TSS_EXCEPTION( eOpenWrite, eErrorGeneral ); +TSS_EXCEPTION( eBadCmdLine, eErrorGeneral ); +TSS_EXCEPTION( eBadModeSwitch, eErrorGeneral ); + +#endif //#ifndef __ERRORGENERAL_H + diff --git a/src/core/errortable.cpp b/src/core/errortable.cpp new file mode 100644 index 0000000..159f64c --- /dev/null +++ b/src/core/errortable.cpp @@ -0,0 +1,81 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// errortable.cpp +// +#include "stdcore.h" +#include "errortable.h" + +#ifdef _DEBUG +#include "package.h" +#include "corestrings.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GetInstance +/////////////////////////////////////////////////////////////////////////////// +cErrorTable* cErrorTable::GetInstance() +{ + static cErrorTable gErrorTable; + return &gErrorTable; +} + +/////////////////////////////////////////////////////////////////////////////// +// AssertMsgValidity +/////////////////////////////////////////////////////////////////////////////// +#ifdef _DEBUG +void cErrorTable::AssertMsgValidity(const TCHAR* msg) +{ + // Check to see that the first part of this error message is not too long. + TSTRING errStr = msg; + + // We only need to check up until the first '\n' since error reporter moves everything + // after that to the "second part". + TSTRING::size_type errSize = errStr.find_first_of(_T('\n')); + if (errSize == TSTRING::npos) + errSize = errStr.length(); + + #if 0 //TODO: Figure out how to do this properly. + TSTRING::size_type errorSize = TSS_GetString( cCore, core::STR_ERROR_ERROR ).length(); + TSTRING::size_type warningSize = TSS_GetString( cCore, core::STR_ERROR_WARNING ).length(); + TSTRING::size_type maxHeaderSize = (errorSize > warningSize ? errorSize : warningSize) + 6; // Add 6 to account for "### ' and ': ' + #else + // Sunpro got stuck in an infinite loop when we called GetString from this func; + TSTRING::size_type errorSize = 9; + TSTRING::size_type warningSize = 10; + TSTRING::size_type maxHeaderSize = (errorSize > warningSize ? errorSize : warningSize) + 6; // Add 6 to account for "### ' and ': ' + #endif + + ASSERT(maxHeaderSize + errSize < 80); +} +#endif + diff --git a/src/core/errortable.h b/src/core/errortable.h new file mode 100644 index 0000000..4b33d2c --- /dev/null +++ b/src/core/errortable.h @@ -0,0 +1,140 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// File: errortable.h +// Date: 30 April 99 +// Creator: mdb +// +// cErrorTable -- singleton derived from Resource_<> that serves as the global +// error id to string mapping +// +#ifndef __ERRORTABLE_H +#define __ERRORTABLE_H + +#ifndef __TSS_RESOURCES_H +#include "resources.h" +#endif +#ifndef __ERROR_H +#include "error.h" +#endif + +class eError; +//----------------------------------------------------------------------------- +// cErrorTable +//----------------------------------------------------------------------------- +class cErrorTable : public cMessages_ +{ +public: + typedef cMessages_ inherited; + + // + // Convenience Methods + // + void Put( const eError& e, const TCHAR* msg ); + // + // Singleton Interface + // + static cErrorTable* GetInstance(); + +private: + #ifdef _DEBUG + static void AssertMsgValidity(const TCHAR* msg); + #endif +}; + +inline void cErrorTable::Put( const eError& e, const TCHAR* msg ) +{ + #ifdef _DEBUG + AssertMsgValidity(msg); + #endif + + inherited::Put( e.GetID(), msg ); +} + +//----------------------------------------------------------------------------- +// Convenience Macros +//----------------------------------------------------------------------------- +// +// These macros make it easy for a module to register errors with the global +// error table. Them like this: +// +// // animalerrors.h +// // +// TSS_DECLARE_ERROR_REGISTRATION( animal ) +// +// // animalerrors.cpp +// // +// TSS_BEGIN_ERROR_REGISTRATION( animal ) +// TSS_REGISTER_ERROR( eDog, _T("Dog error") ) +// TSS_REGISTER_ERROR( eDogBark, _T("Barking error") ) +// TSS_END_ERROR_REGISTRATION() +// +// // pkg.h +// TSS_DeclarePackage( cWorld ) +// +// // pkg.cpp +// cWorld::cWorld() +// { +// TSS_REGISTER_PKG_ERRORS( animal ) +// +//=================== +// cpp file macros +//=================== +#define TSS_BEGIN_ERROR_REGISTRATION( pkgName ) \ + RegisterErrors##pkgName::RegisterErrors##pkgName() \ + { + +#define TSS_REGISTER_ERROR( err, str ) \ + cErrorTable::GetInstance()->Put \ + ( err, str ); + +#define TSS_END_ERROR_REGISTRATION() \ + } + +//=================== +// h file macros +//=================== +#define TSS_DECLARE_ERROR_REGISTRATION( pkgName ) \ + struct RegisterErrors##pkgName \ + {\ + RegisterErrors##pkgName(); \ + }; + +//=================== +// package init macros +//=================== +#define TSS_REGISTER_PKG_ERRORS( pkgName ) \ + RegisterErrors##pkgName register##pkgName; + + +#endif //__ERRORTABLE_H + diff --git a/src/core/errorutil.cpp b/src/core/errorutil.cpp new file mode 100644 index 0000000..53d15e1 --- /dev/null +++ b/src/core/errorutil.cpp @@ -0,0 +1,87 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// errorutil.cpp +// +#include "stdcore.h" +#include "errorutil.h" +#include "corestrings.h" + +//============================================================================= +// class eInternal +//============================================================================= + +#if IS_UNIX +namespace //unique +{ + + TCHAR* _itot( int value, TCHAR* string, int radix) + { + _stprintf( string, "%d", value ); + return string; + } +} +#endif + +eInternal::eInternal(TCHAR* sourceFile, int lineNum) +: eError(_T("")) +{ + TCHAR buf[256]; + + mMsg = _T("File: "); + mMsg += sourceFile; + mMsg += _T(" Line: "); + mMsg += _itot(lineNum, buf, 10); +} + +//============================================================================= +// class cErrorUtil +//============================================================================= + +/////////////////////////////////////////////////////////////////////////////// +// MakeFileError +/////////////////////////////////////////////////////////////////////////////// +TSTRING cErrorUtil::MakeFileError( const TSTRING& msg, const TSTRING& fileName ) +{ + TSTRING ret; + ret = TSS_GetString( cCore, core::STR_ERR2_FILENAME ); + ret.append( fileName ); + ret.append( 1, _T('\n') ); + + if ( msg.length() > 0 ) + { + ret.append(msg); + } + + return ret; +} + diff --git a/src/core/errorutil.h b/src/core/errorutil.h new file mode 100644 index 0000000..f50af25 --- /dev/null +++ b/src/core/errorutil.h @@ -0,0 +1,173 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// File: errorutil.h +// Date: 30 April 99 +// Creator: mdb +// Company: TSS +// Desc: contains useful eError derived classes +// +// eInternal -- internal logic errors ( ie -- programming mistakes ) +// ePoly -- "polymorphic" error that takes its ID as input instead +// of from its class name +// ThrowAndAssert -- asserts false and throws the specified exception +// +#ifndef __ERRORUTIL_H +#define __ERRORUTIL_H + +#ifndef __ERROR_H +#include "error.h" +#endif + + +//----------------------------------------------------------------------------- +// ePoly +//----------------------------------------------------------------------------- +class ePoly : public eError +{ +public: + //------------------------------------------------------------------------- + // Construction and Assignment + //------------------------------------------------------------------------- + ePoly( uint32 id, const TSTRING& msg, uint32 flags = 0 ); + explicit ePoly( const eError& rhs ); + explicit ePoly(); + void operator=( const eError& rhs ); + + //------------------------------------------------------------------------- + // ID manipulation + //------------------------------------------------------------------------- + virtual uint32 GetID() const; + void SetID( uint32 id ); + +private: + uint32 mID; +}; + +//----------------------------------------------------------------------------- +// eInternal +//----------------------------------------------------------------------------- +TSS_BEGIN_EXCEPTION( eInternal, eError ) +public: + eInternal( TCHAR* file, int lineNum ); +TSS_END_EXCEPTION() + +//----------------------------------------------------------------------------- +// cErrorUtil +//----------------------------------------------------------------------------- +class cErrorUtil +{ +public: + static TSTRING MakeFileError( const TSTRING& msg, const TSTRING& fileName ); + // constructs an error message of the form: + // File: \n + // This is useful for constructing strings to pass as the msg parameter + // to eError constructors. +}; + +//----------------------------------------------------------------------------- +// Convenience Macros +//----------------------------------------------------------------------------- +// +// NOTE -- we require the developer to supply the file name instead of using +// __FILE__ because that includes the full path to the file, which we +// would not like to display to the user. +// +#define INTERNAL_ERROR(filename) eInternal((TCHAR*)_T(filename), __LINE__) +#define THROW_INTERNAL(filename) throw eInternal((TCHAR*)_T(filename), __LINE__) + + +// TODO: ASSERT is always fatal in Unix, perhaps we could #ifdef the ASSERT +// to echo to cout the line number the exception occured at? +#define ThrowAndAssert(exception) { ASSERT(false); throw exception; } + + +//----------------------------------------------------------------------------- +// Inline Implementation +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// ePoly +/////////////////////////////////////////////////////////////////////////////// +inline ePoly::ePoly( uint32 id, const TSTRING& msg, uint32 flags ) +: eError( msg, flags ), + mID( id ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// ePoly +/////////////////////////////////////////////////////////////////////////////// +inline ePoly::ePoly( const eError& rhs ) +{ + *this = rhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// ePoly +/////////////////////////////////////////////////////////////////////////////// +inline ePoly::ePoly() +: eError( _T("") ), + mID( 0 ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +inline void ePoly::operator=( const eError& rhs ) +{ + mMsg = rhs.GetMsg(); + mFlags = rhs.GetFlags(); + mID = rhs.GetID(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetID +/////////////////////////////////////////////////////////////////////////////// +inline uint32 ePoly::GetID() const +{ + return mID; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetID +/////////////////////////////////////////////////////////////////////////////// +inline void ePoly::SetID( uint32 id ) +{ + mID = id; +} + +#endif //__ERRORUTIL_H + diff --git a/src/core/file.h b/src/core/file.h new file mode 100644 index 0000000..a29d7d7 --- /dev/null +++ b/src/core/file.h @@ -0,0 +1,144 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// file.h : Interface for cFile class, which abstracts file operations across +// different platforms (currently just Windows and Unix...) + +#ifndef __FILE_H +#define __FILE_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __FILEERROR_H +#include "fileerror.h" +#endif + + + +//============================================================================= +// eFile exception class +//============================================================================= + +TSS_FILE_EXCEPTION( eFile, eFileError ); +TSS_FILE_EXCEPTION( eFileOpen, eFile ); +TSS_FILE_EXCEPTION( eFileWrite, eFile ); +TSS_FILE_EXCEPTION( eFileRead, eFile ); +TSS_FILE_EXCEPTION( eFileEOF, eFile ); // never used! +TSS_FILE_EXCEPTION( eFileSeek, eFile ); +TSS_FILE_EXCEPTION( eFileInvalidOp, eFile ); // never used! +TSS_FILE_EXCEPTION( eFileTrunc, eFile ); +TSS_FILE_EXCEPTION( eFileClose, eFile ); // never used! +TSS_FILE_EXCEPTION( eFileFlush, eFile ); +TSS_FILE_EXCEPTION( eFileRewind, eFile ); + +//============================================================================= +// cFile +//============================================================================= +struct cFile_i; +class cFile +{ +public: +#if IS_UNIX + typedef int32 File_t; + +#else //WIN32 + typedef int64 File_t; + +#endif // IS_UNIX + + enum SeekFrom + { + SEEK_BEGIN = 0, + SEEK_CURRENT, + SEEK_EOF + }; + + enum OpenFlags + { + // note that reading from the file is implicit + // + OPEN_READ = 0x00000001, // not needed, but makes calls nice... + OPEN_WRITE = 0x00000002, // we will be writing to the file + OPEN_LOCKED_TEMP = 0x00000004, // the file should not be readable by other processes and should be removed when closed + OPEN_TRUNCATE = 0x00000008, // opens an empty file. creates it if it doesn't exist. Doesn't make much sense without OF_WRITE + OPEN_CREATE = 0x00000010, // create the file if it doesn't exist; this is implicit if OF_TRUNCATE is set + OPEN_TEXT = 0x00000020, + OPEN_EXCLUSIVE = 0x00000040 // Use O_CREAT | O_EXCL + }; + + //Ctor, Dtor, CpyCtor, Operator=: + cFile ( void ); + ~cFile ( void ); + + /************ User Interface **************************/ + + // Both Open methods ALWAYS open files in BINARY mode! + void Open ( const TSTRING& sFileName, uint32 flags = OPEN_READ ); //throw(eFile) + void Close ( void ); //throw(eFile) + bool IsOpen ( void ) const; + + File_t Seek ( File_t offset, SeekFrom From ) const; //throw(eFile) + // Seek returns the current offset after completion + File_t Read ( void* buffer, File_t nBytes ) const; //throw(eFile) + // Read returns the number of bytes that are actually read. If the nBytes + // parameter is 0, 0 bytes will be read and buffer will remain untouched. + // If the read head is at EOF, no bytes will be read and 0 will be returned. + File_t Write ( const void* buffer, File_t nBytes ); //throw(eFile) + // Write returns the number of bytes that are actually written. + File_t Tell ( void ) const; + // Tell returns the current offset. + bool Flush ( void ); //throw(eFile) + // Flush returns 0 if the currently defined stream is successfully flushed. + void Rewind ( void ) const; //throw(eFile) + // Sets the offset to 0. + File_t GetSize ( void ) const; + // Returns the size of the current file in bytes. Returns -1 if no file is defined. + void Truncate ( File_t offset ); // throw(eFile) + +private: + cFile ( const cFile& rhs ); //not impl. + cFile& operator= ( const cFile& rhs); //not impl. + + //Pointer to the insulated implementation + cFile_i* mpData; + +public: + bool isWritable; +}; + +#endif //__FILE_H + diff --git a/src/core/file_t.cpp b/src/core/file_t.cpp new file mode 100644 index 0000000..d6f948b --- /dev/null +++ b/src/core/file_t.cpp @@ -0,0 +1,79 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// file_t.cpp : A test harness for cFile, a class for abstracting +// file operations between different platforms. + +#include "stdcore.h" +#include "file.h" +#include "test/test.h" +#include + +void TestFile() +{ + + TSTRING fileName = TEMP_DIR; + fileName += _T("/file_test.bin"); + + //Create a temporary file for testing: + FILE* testStream; + testStream = _tfopen( fileName.c_str(), _T("w+b")); + TSTRING testString( _T("This is a test") ); + int iTestStringLength = testString.length(); + + //Write some data to the stream... + fwrite( testString.c_str(), sizeof(TCHAR), iTestStringLength, testStream ); + fclose( testStream ); + + //Open the file again, for reading only this time. + testStream = _tfopen( fileName.c_str(), _T("rb") ); + + cFile fTempFile; + //Try attaching one of our file objects to the stream. +//TODO: fTempFile.AttachRead( testStream ); + + //Try reading something from the file object + TCHAR buffer[40]; + TCHAR buffer2[40]; + + fTempFile.Read( buffer, sizeof(TCHAR) * iTestStringLength ); + fTempFile.Close(); + + testStream = _tfopen( fileName.c_str(), _T("a+b") ); +//TODO: fTempFile.AttachReadWrite( testStream ); + + //Now try writing something to the stream. + fTempFile.Write( testString.c_str(), sizeof(TCHAR) * iTestStringLength ); + fTempFile.Rewind(); + fTempFile.Read( buffer2, sizeof(TCHAR) * iTestStringLength * 2 ); + +} + diff --git a/src/core/file_unix.cpp b/src/core/file_unix.cpp new file mode 100644 index 0000000..d63ed5f --- /dev/null +++ b/src/core/file_unix.cpp @@ -0,0 +1,371 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// file_unix.cpp : Specific implementation of file operations for Unix. + +#include "core/stdcore.h" + +#if !IS_UNIX +#error Need to be unix to use unixfsservices +#endif + +#include "core/file.h" + +#include +#include +#include +#include +#include +#include + +#include "core/debug.h" +#include "core/corestrings.h" +#include "core/fsservices.h" +#include "core/errorutil.h" + +/////////////////////////////////////////////////////////////////////////////// +// util_GetErrnoString -- return the result of strerror(errno) as a tstring +/////////////////////////////////////////////////////////////////////////////// +static TSTRING util_GetErrnoString() +{ + TSTRING ret; + char* pErrorStr = strerror(errno); +#ifdef _UNICODE +#error We dont currently support unicode on unix +#else + ret = pErrorStr; +#endif + return ret; +} + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// cFile_i : Insulated implementation for cFile objects. +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +struct cFile_i +{ + cFile_i(); + ~cFile_i(); + + FILE* mpCurrStream; //currently defined file stream + TSTRING mFileName; //the name of the file we are currently referencing. +}; + +//Ctor +cFile_i::cFile_i() : + mpCurrStream(NULL) +{} + +//Dtor +cFile_i::~cFile_i() +{ + if (mpCurrStream != NULL) + fclose( mpCurrStream ); + mpCurrStream = NULL; + + mFileName.empty(); +} + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// cFile () -- Implements file operations +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +cFile::cFile() : + mpData(NULL), isWritable(false) +{ + mpData = new cFile_i; +} + +cFile::~cFile() +{ + if( mpData != NULL) + { + delete mpData; + mpData = NULL; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Open +/////////////////////////////////////////////////////////////////////////////// +void cFile::Open( const TSTRING& sFileName, uint32 flags ) +{ + mode_t openmode = 0664; + if ( mpData->mpCurrStream != NULL ) + Close(); + + // + // set up the sopen permissions + // + int perm = 0; + + TSTRING mode; + + if( flags & OPEN_WRITE ) + { + perm |= O_RDWR; + isWritable = true; + mode = _T("rb"); + if( flags & OPEN_TRUNCATE ) + { + perm |= O_TRUNC; + perm |= O_CREAT; + mode = _T("w+b"); + } + else + mode = _T("r+b"); + } + else + { + perm |= O_RDONLY; + isWritable = false; + mode = _T("rb"); + } + + if ( flags & OPEN_EXCLUSIVE ) { + perm |= O_CREAT | O_EXCL; + openmode = (mode_t) 0600; // Make sure only root can read the file + } + + if ( flags & OPEN_CREATE ) + perm |= O_CREAT; + + // + // actually open the file + // + int fh = _topen( sFileName.c_str(), perm, openmode ); + if( fh == -1 ) + { + throw( eFileOpen( sFileName, iFSServices::GetInstance()->GetErrString() ) ); + } + if( flags & OPEN_LOCKED_TEMP ) + { + // unlink this file + if( 0 != unlink( sFileName.c_str() ) ) + { + // we weren't able to unlink file, so close handle and fail + close( fh ); + throw( eFileOpen( sFileName, iFSServices::GetInstance()->GetErrString() ) ); + } + } + + // + // turn the file handle into a FILE* + // + mpData->mpCurrStream = _tfdopen(fh, mode.c_str()); + + mpData->mFileName = sFileName; //Set mFileName to the newly opened file. + + cFile::Rewind(); +} + + +/////////////////////////////////////////////////////////////////////////// +// Close -- Closes mpCurrStream and sets the pointer to NULL +/////////////////////////////////////////////////////////////////////////// +void cFile::Close() //throw(eFile) +{ + if(mpData->mpCurrStream != NULL) + { + fclose( mpData->mpCurrStream ); + mpData->mpCurrStream = NULL; + } + mpData->mFileName.empty(); +} + +bool cFile::IsOpen( void ) const +{ + return( mpData->mpCurrStream != NULL ); +} + +/////////////////////////////////////////////////////////////////////////// +// Seek -- Positions the read/write offset in mpCurrStream. Returns the +// current offset upon completion. Returns 0 if no stream is defined. +/////////////////////////////////////////////////////////////////////////// +cFile::File_t cFile::Seek( File_t offset, SeekFrom From) const //throw(eFile) +{ + //Check to see if a file as been opened yet... + ASSERT( mpData->mpCurrStream != 0); + + int apiFrom; + + switch( From ) + { + case cFile::SEEK_BEGIN: + apiFrom = SEEK_SET; + break; + case cFile::SEEK_CURRENT: + apiFrom = SEEK_CUR; + break; + case cFile::SEEK_EOF: + apiFrom = SEEK_END; + break; + default: + //An invalid SeekFrom parameter was passed. + throw( eInternal( _T("file_unix") ) ); + } + + // this is a hack to simulate running out of disk space + #if 0 + static int blowupCount = 1; + if (++blowupCount == 1075) + { + fputs("***** faking seek failure!\n", stderr); + //throw eFileSeek(); + throw std::bad_alloc(); + } + fprintf(stderr, "%d\n", blowupCount); + #endif + + if (fseek( mpData->mpCurrStream, offset, apiFrom ) != 0) + { + #ifdef _DEBUG + cDebug d("cFile::Seek"); + d.TraceDebug("Seek failed!\n"); + #endif + throw eFileSeek(); + } + + return ftell( mpData->mpCurrStream ); +} + +/////////////////////////////////////////////////////////////////////////// +// Read -- Returns the actual bytes read from mpCurrStream. Returns 0 if +// mpCurrStream is undefined. +/////////////////////////////////////////////////////////////////////////// +cFile::File_t cFile::Read( void* buffer, File_t nBytes ) const //throw(eFile) +{ + File_t iBytesRead; + + // Has a file been opened? + ASSERT( mpData->mpCurrStream != NULL ); + + // Is the nBytes parameter 0? If so, return without touching buffer: + if( nBytes == 0 ) + return 0; + + iBytesRead = fread( buffer, sizeof(byte), nBytes, mpData->mpCurrStream ); + + if( ferror( mpData->mpCurrStream ) != 0 ) + throw eFileRead( mpData->mFileName, iFSServices::GetInstance()->GetErrString() ) ; + else + return iBytesRead; +} + +/////////////////////////////////////////////////////////////////////////// +// Write -- Returns the actual number of bytes written to mpCurrStream +// Returns 0 if no file has been opened. +/////////////////////////////////////////////////////////////////////////// +cFile::File_t cFile::Write( const void* buffer, File_t nBytes ) //throw(eFile) +{ + File_t actual_count = 0; + + // Has a file been opened? Is it writable? + ASSERT( mpData->mpCurrStream != NULL ); + ASSERT( isWritable ); + + if( ( actual_count = fwrite( buffer, sizeof(byte), nBytes, mpData->mpCurrStream ) ) < nBytes ) + throw eFileWrite( mpData->mFileName, iFSServices::GetInstance()->GetErrString() ); + else + return actual_count; +} + +/////////////////////////////////////////////////////////////////////////// +// Tell -- Returns the current file offset. Returns 0 if no file has been +// opened. +/////////////////////////////////////////////////////////////////////////// +cFile::File_t cFile::Tell() const +{ + ASSERT( mpData->mpCurrStream != 0); + + return ftell( mpData->mpCurrStream ); +} + +/////////////////////////////////////////////////////////////////////////// +// Flush -- Flushes the current stream. +/////////////////////////////////////////////////////////////////////////// +bool cFile::Flush() //throw(eFile) +{ + if ( mpData->mpCurrStream == NULL ) + throw eFileFlush( mpData->mFileName, iFSServices::GetInstance()->GetErrString() ); + + return ( fflush( mpData->mpCurrStream) == 0 ); +} +/////////////////////////////////////////////////////////////////////////// +// Rewind -- Sets the offset to the beginning of the file. If mpCurrStream +// is NULL, this method returns false. If the rewind operation fails, +// an exception is thrown. +/////////////////////////////////////////////////////////////////////////// +void cFile::Rewind() const //throw(eFile) +{ + ASSERT( mpData->mpCurrStream != 0); + + rewind( mpData->mpCurrStream ); + if( ftell( mpData->mpCurrStream ) != 0 ) + throw( eFileRewind( mpData->mFileName, iFSServices::GetInstance()->GetErrString() ) ); +} + +/////////////////////////////////////////////////////////////////////////// +// GetSize -- Returns the size of the current stream, if one has been +// opened. If no stream has been opened, returns -1. +/////////////////////////////////////////////////////////////////////////// +cFile::File_t cFile::GetSize() const +{ + File_t vCurrentOffset = Tell(); //for saving the current offset + File_t ret; + + //Has a file been opened? If not, return -1 + if( mpData->mpCurrStream == NULL ) + return -1; + + ret = Seek( 0, cFile::SEEK_EOF ); + Seek( vCurrentOffset, cFile::SEEK_BEGIN ); + //return the offset to it's position prior to GetSize call. + + return ret; +} + +///////////////////////////////////////////////////////////////////////// +// Truncate +///////////////////////////////////////////////////////////////////////// +void cFile::Truncate( File_t offset ) // throw(eFile) +{ + ASSERT( mpData->mpCurrStream != 0); + ASSERT( isWritable ); + + ftruncate( fileno(mpData->mpCurrStream), offset ); + if( GetSize() != offset ) + throw( eFileTrunc( mpData->mFileName, iFSServices::GetInstance()->GetErrString() ) ); +} + diff --git a/src/core/fileerror.cpp b/src/core/fileerror.cpp new file mode 100644 index 0000000..adbb129 --- /dev/null +++ b/src/core/fileerror.cpp @@ -0,0 +1,76 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileerror.cpp -- file error exception class +// +#include "stdcore.h" +#include "fileerror.h" +#include "corestrings.h" + +// TODO: Make this use MakeFileError() for consistency +eFileError::eFileError( const TSTRING& filename, const TSTRING& description, uint32 flags ) +: eError( _T(""), flags ) +{ + mFilename = filename; + mMsg = description; +} + +TSTRING eFileError::GetFilename() const +{ + return mFilename; +} + +TSTRING eFileError::GetDescription() const +{ + return mMsg; +} + +/* virtual */ TSTRING eFileError::GetMsg() const +{ + TSTRING ret; + + if( ! mFilename.empty() ) + { + ret = TSS_GetString( cCore, core::STR_ERROR_FILENAME ) + mFilename; + } + + if( ! mMsg.empty() ) + { + if ( ! mFilename.empty() ) + ret += _T("\n"); + + ret += mMsg; + } + + return ret; +} + diff --git a/src/core/fileerror.h b/src/core/fileerror.h new file mode 100644 index 0000000..db7f0bb --- /dev/null +++ b/src/core/fileerror.h @@ -0,0 +1,80 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileerror.h -- file error exception class +// + +#ifndef __FILEERROR_H +#define __FILEERROR_H + +#ifndef __ERROR_H +#include "error.h" +#endif + +//============================================================================= +// class eFileError +// +// This error class is useful for errors that need to specify a filename. +// cTWUtil::PrintErrorMsg() returns text similar to the following: +// +// ### Error: File Access denied. <-- text associated with errorNum +// ### Filename: C:\foo\bar.txt <-- constructor parameter "filename" +// ### Insufficient permission to open file. <-- constructor parameter "msg" +// ### Exiting... <-- appropriate third message +//============================================================================= +TSS_BEGIN_EXCEPTION_NO_CTOR( eFileError, eError ) +private: + TSTRING mFilename; + +public: + eFileError( const TSTRING& filename, const TSTRING& description, uint32 flags = 0 ); + + explicit eFileError( const eFileError& rhs ) + : eError( rhs ) { mFilename = rhs.mFilename; } + eFileError( const TSTRING& msg, uint32 flags = 0 ) + : eError( msg, flags ) {} + + + TSTRING GetFilename() const; + TSTRING GetDescription() const; + virtual TSTRING GetMsg() const; + +TSS_END_EXCEPTION() + +#define TSS_FILE_EXCEPTION( except, base ) \ + TSS_BEGIN_EXCEPTION( except, base ) \ + except( const TSTRING& filename, const TSTRING& msg, uint32 flags = 0 ) \ + : base( filename, msg, flags ) {} \ + TSS_END_EXCEPTION() + +#endif + diff --git a/src/core/fileheader.cpp b/src/core/fileheader.cpp new file mode 100644 index 0000000..fed64bd --- /dev/null +++ b/src/core/fileheader.cpp @@ -0,0 +1,278 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileheader.cpp + +#include "stdcore.h" +#include "fileheader.h" +#include "serializer.h" +#include "ntmbs.h" + +// A magic number to put at top of file headers +// I changed this magic number in 2.1 since we now support versioning in the file header. +// (the old magic number was 0x00202039) +// I generated the random number using the random.org web site. +const uint32 FILE_HEADER_MAGIC_NUMBER = 0x78f9beb3; + +/////////////////////////////////////////////////////////////////////////////// +// class cFileHeaderID + +cFileHeaderID::~cFileHeaderID() +{ +} + +void cFileHeaderID::operator=( const TCHAR* pszId ) +{ + // RAD:10/1/99 -- Not Needed + // TODO:BAM -- I'm pretty sure that there's a bug hiding here... + //size_t len = _tcslen(id); + //if (len >= 256) + //{ + // ASSERT(false); + // mIDLen = 0; + // return; + //} + +#ifdef _UNICODE + + size_t N = (::wcslen( pszId ) * MB_CUR_MAX); // Try the easy way! + if ( !(N < cFileHeaderID::MAXBYTES) ) + { + N = ::wcstombs( 0, pszId, (size_t)-1 ); // Try again! + if ( N == (size_t)-1 ) + { + throw + eCharacterEncoding( + TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + else if ( !(N < cFileHeaderID::MAXBYTES) ) + { + throw + eCharacter( + TSS_GetString( cCore, core::STR_ERR_OVERFLOW ) ); + } + } + + mIDLen = (int16)(::wcstombs( mID, pszId, N )); // Do it + +#else + + size_t N = ::strlen( pszId ); + if ( !(N < cFileHeaderID::MAXBYTES) ) + throw eCharacter( TSS_GetString( cCore, core::STR_ERR_OVERFLOW ) ); + + mIDLen = static_cast( N ); // know len is less than MAXBYTES + ::memcpy( mID, pszId, N * sizeof(char) ); + +#endif +} + +void cFileHeaderID::operator=( const cFileHeaderID& rhs ) +{ + ASSERT( rhs.mIDLen < cFileHeaderID::MAXBYTES ); + mIDLen = rhs.mIDLen; + memcpy(mID, rhs.mID, mIDLen * sizeof(char)); +} + +int cFileHeaderID::operator==( const cFileHeaderID& rhs ) const +{ + return + ( mIDLen == rhs.mIDLen ) && + ( ::memcmp( mID, rhs.mID, mIDLen * sizeof(char) ) == 0 ); +} + +void cFileHeaderID::Read(iSerializer* pSerializer, int32 /*version*/ ) // throw (eSerializer, eArchive) +{ + int16 len; + pSerializer->ReadInt16( len ); + if ( (len < 0) || (len >= cFileHeaderID::MAXBYTES )) + { + // this is invalid! + throw eSerializerInputStreamFmt( _T("File Header ID invalid") ); + } + pSerializer->ReadBlob(mID, len * sizeof(char)); + mIDLen = len; +} + +void cFileHeaderID::Write(iSerializer* pSerializer) const // throw (eSerializer, eArchive) +{ + ASSERT( mIDLen >= 0 && mIDLen < cFileHeaderID::MAXBYTES ); + + pSerializer->WriteInt16( mIDLen ); + pSerializer->WriteBlob( mID, mIDLen * sizeof(char) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cFileHeader + +cFileHeader::cFileHeader() +: mVersion(0) +{ +#ifdef _DEBUG + mEncoding = LAST_ENCODING; // set to invalid value so we can assert on write +#else + mEncoding = NO_ENCODING; +#endif +} + +cFileHeader::cFileHeader(const cFileHeader& rhs) +: mID(rhs.mID), + mVersion(rhs.mVersion), + mEncoding(rhs.mEncoding) +{ + if (rhs.mBaggage.Length() > 0) + { + mBaggage.MapArchive(0, rhs.mBaggage.Length()); + rhs.mBaggage.MapArchive(0, rhs.mBaggage.Length()); + + ::memcpy( + mBaggage.GetMap(), + rhs.mBaggage.GetMap(), + static_cast( rhs.mBaggage.Length() ) ); + + mBaggage.MapArchive(0, 0); + rhs.mBaggage.MapArchive(0, 0); + } +} + +cFileHeader::~cFileHeader() +{ +} + +void cFileHeader::SetID(const cFileHeaderID& id) +{ + mID = id; +} + +void cFileHeader::SetVersion(uint32 v) +{ + mVersion = v; +} + +void cFileHeader::SetEncoding(Encoding e) +{ + mEncoding = e; +} + +void cFileHeader::Read(iSerializer* pSerializer, int32 /*version*/) // throw (eSerializer, eArchive) +{ + int16 e; + int32 len; + int32 magicNumber; + int32 version; + + cDebug d("cFileHeader::Read"); + + pSerializer->ReadInt32(magicNumber); + if ((unsigned int)magicNumber != FILE_HEADER_MAGIC_NUMBER) + { + d.TraceDebug("Bad magic number"); + throw eSerializerInputStreamFmt(pSerializer->GetFileName() ); + } + + // Note this version refers to the format of this data structure in the + // file image. mVersion refers to the version of data that accompanies + // this cFileHeader, for example the database or report format. + pSerializer->ReadInt32(version); + if (version > 1) + { + // don't understand the version + d.TraceDebug("Bad version"); + throw eSerializerInputStreamFmt(pSerializer->GetFileName() ); + } + + mID.Read(pSerializer); + + pSerializer->ReadInt32(version); + mVersion = version; + + pSerializer->ReadInt16(e); + mEncoding = (Encoding)e; + + pSerializer->ReadInt32(len); + + if (len < 0 || len > 0xffff) + throw eSerializerInputStreamFmt(pSerializer->GetFileName() ); + + mBaggage.MapArchive(0, len); + + if (len > 0) + { + mBaggage.MapArchive(0, len); + pSerializer->ReadBlob(mBaggage.GetMap(), len); + } + + mBaggage.Seek(len, cBidirArchive::BEGINNING); + mBaggage.Truncate(); + mBaggage.Seek(0, cBidirArchive::BEGINNING); +} + +void cFileHeader::Write(iSerializer* pSerializer) const // throw (eSerializer, eArchive) +{ +#ifdef _DEBUG + // check that we set some values + cFileHeaderID id; + ASSERT(mID != id); + ASSERT(mEncoding != LAST_ENCODING); +#endif + + // we need to have our own versioning since we are not + // a iTypedSerializable object. + pSerializer->WriteInt32(FILE_HEADER_MAGIC_NUMBER); + + // Note this version refers to the format of this data structure in the + // file image. mVersion refers to the version of data that accompanies + // this cFileHeader, for example the database or report format. + pSerializer->WriteInt32(1); // version + + mID.Write(pSerializer); + + pSerializer->WriteInt32(mVersion); + + pSerializer->WriteInt16( static_cast(mEncoding) ); + + int32 len = static_cast( mBaggage.Length() ); + + ASSERT(len >= 0); + ASSERT(len <= 0xFFFF); + + if ( len < 0 || len > 0xFFFF ) + throw eSerializerOutputStreamFmt(); + + pSerializer->WriteInt32(len); + if (len > 0) + { + mBaggage.MapArchive(0, len); + pSerializer->WriteBlob(mBaggage.GetMap(), len); + } +} + diff --git a/src/core/fileheader.h b/src/core/fileheader.h new file mode 100644 index 0000000..c0404a5 --- /dev/null +++ b/src/core/fileheader.h @@ -0,0 +1,166 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileheader.h + +#ifndef __FILEHEADER_H +#define __FILEHEADER_H + +#ifndef __ARCHIVE_H +#include "archive.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cFileHeaderID + +class cFileHeaderID : public iSerializable +{ +public: + cFileHeaderID(); + cFileHeaderID(const TCHAR* id); + cFileHeaderID(const cFileHeaderID& rhs); + virtual ~cFileHeaderID(); + + void operator = (const TCHAR* id); + void operator = (const cFileHeaderID& rhs); + int operator == (const cFileHeaderID& rhs) const; + int operator != (const cFileHeaderID& rhs) const; + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +private: + // For now we will store the id as a string. + // At some point we may want to make this more efficient like + // the way we implemented cFCONames. + // Note: We store the string as narrow chars, since + // the program is the only person who will see them. + int16 mIDLen; + + enum { MAXBYTES = 256 }; + char mID[ MAXBYTES ]; +}; + +inline cFileHeaderID::cFileHeaderID() +{ + mIDLen = 0; +} + +inline cFileHeaderID::cFileHeaderID(const TCHAR* id) +{ + *this = id; +} + +inline +cFileHeaderID::cFileHeaderID( const cFileHeaderID& rhs ) : + mIDLen( rhs.mIDLen ) +{ + memcpy( mID, rhs.mID, MAXBYTES ); +} + +inline int cFileHeaderID::operator != (const cFileHeaderID& rhs) const +{ + return !(*this == rhs); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cFileHeader + +class cFileHeader : public iSerializable +{ +public: + cFileHeader(); + cFileHeader(const cFileHeader& rhs); + virtual ~cFileHeader(); + + enum Encoding + { + NO_ENCODING = 0, + COMPRESSED, + ASYM_ENCRYPTION, + SYM_ENCRYPTION, + LAST_ENCODING + }; + + void SetID(const cFileHeaderID& id); + const cFileHeaderID& GetID() const; + + void SetVersion(uint32 v); + uint32 GetVersion() const; + + void SetEncoding(Encoding e); + Encoding GetEncoding() const; + + cMemoryArchive& GetBaggage(); + const cMemoryArchive& GetBaggage() const; + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + cFileHeaderID mID; + uint32 mVersion; + Encoding mEncoding; + cMemoryArchive mBaggage; // items that have been serialized to this object +}; + +inline const cFileHeaderID& cFileHeader::GetID() const +{ + return mID; +} + +inline uint32 cFileHeader::GetVersion() const +{ + return mVersion; +} + +inline cFileHeader::Encoding cFileHeader::GetEncoding() const +{ + return mEncoding; +} + +inline cMemoryArchive& cFileHeader::GetBaggage() +{ + return mBaggage; +} + +inline const cMemoryArchive& cFileHeader::GetBaggage() const +{ + return mBaggage; +} + +#endif + diff --git a/src/core/fileheader_t.cpp b/src/core/fileheader_t.cpp new file mode 100644 index 0000000..8bf276d --- /dev/null +++ b/src/core/fileheader_t.cpp @@ -0,0 +1,128 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileheader_t.cpp + +#include "stdcore.h" +#include "fileheader.h" +#include "test/test.h" +#include "serializerimpl.h" +#include "archive.h" + +void TestFileHeader() +{ + cMemoryArchive memarch; + + // cFileHeaderID testing + cFileHeaderID id(_T("testheader1")); + cFileHeaderID id_dup(id); + cFileHeaderID id_null; + + TEST(id == id); + TEST(id == id_dup); + TEST(id != id_null); + + { + cSerializerImpl ser(memarch, cSerializerImpl::S_WRITE); + + ser.Init(); + id.Write(&ser); + id_dup.Write(&ser); + id_null.Write(&ser); + ser.Finit(); + } + + memarch.Seek(0, cBidirArchive::BEGINNING); + + { + cSerializerImpl ser(memarch, cSerializerImpl::S_READ); + cFileHeaderID id_read; + + ser.Init(); + id_read.Read(&ser); + TEST(id_read == id); + id_read.Read(&ser); + TEST(id_read == id_dup); + id_read.Read(&ser); + TEST(id_read == id_null); + ser.Finit(); + } + + memarch.Seek(0, cBidirArchive::BEGINNING); + memarch.Truncate(); + + + // cFileHeader testing + cFileHeader header1; + cFileHeader header2; + + header1.SetID(cFileHeaderID(_T("myheader"))); + TEST(header1.GetID() == cFileHeaderID(_T("myheader"))); + header1.SetEncoding(cFileHeader::SYM_ENCRYPTION); + TEST(header1.GetEncoding() == cFileHeader::SYM_ENCRYPTION); + + header2.SetID(id); + TEST(header2.GetID() == id); + header2.SetEncoding(cFileHeader::COMPRESSED); + header2.GetBaggage().WriteBlob("abc123", 6); + + { + cSerializerImpl ser(memarch, cSerializerImpl::S_WRITE); + + ser.Init(); + header1.Write(&ser); + header2.Write(&ser); + ser.Finit(); + } + + memarch.Seek(0, cBidirArchive::BEGINNING); + + { + cSerializerImpl ser(memarch, cSerializerImpl::S_READ); + cFileHeader header_read; + + ser.Init(); + header_read.Read(&ser); + TEST(header_read.GetID() == header1.GetID()); + TEST(header_read.GetEncoding() == header1.GetEncoding()); + TEST(header_read.GetBaggage().Length() == 0); + header_read.Read(&ser); + TEST(header_read.GetID() == header2.GetID()); + TEST(header_read.GetEncoding() == header2.GetEncoding()); + TEST(header_read.GetBaggage().Length() != 0); + ser.Finit(); + + char buf[6]; + header_read.GetBaggage().ReadBlob(buf, 6); + TEST(memcmp(buf, "abc123", 6) == 0); + } +} diff --git a/src/core/fixedfilebuf.h b/src/core/fixedfilebuf.h new file mode 100644 index 0000000..adf7d00 --- /dev/null +++ b/src/core/fixedfilebuf.h @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fixed_filebuf.h +// Date....: 8/12/99 +// Creator.: Brian McFeely (bmcfeely) +// +// Plauger's 'basic_filebuf::overflow' had a bug, +// so I had to reimplement the entire class. +// +// Plauger had a line: "fwrite(_Str->begin(), _N, 1, _File)" +// that should have been: "fwrite(_Str->begin(), 1, _N, _File)" +// + +#ifndef __FIXED_FILEBUF_H +#define __FIXED_FILEBUF_H + +#include + +#if IS_UNIX +#define fixed_basic_ofstream std::basic_ofstream +#endif // IS_WIN32/IS_UNIX + +#endif//__FIXED_FILEBUF_H + diff --git a/src/core/fsservices.cpp b/src/core/fsservices.cpp new file mode 100644 index 0000000..7f68d62 --- /dev/null +++ b/src/core/fsservices.cpp @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fsservices.cpp +#include "stdcore.h" +#include "fsservices.h" +#include "debug.h" +// required for errno +#include +#include +#include "corestrings.h" + +iFSServices* iFSServices::mpInstance = 0; + +//############################################################################# +// eFSServices +//############################################################################# + + diff --git a/src/core/fsservices.h b/src/core/fsservices.h new file mode 100644 index 0000000..78d58fc --- /dev/null +++ b/src/core/fsservices.h @@ -0,0 +1,400 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsservices.h +// +// iFSServices -- interface to the file system services class +// +// objective: +// abstract all file system calls, except for reading/writing +// to elaborate: this class does not handle any file I/O -- we +// intend to use streams to abstract out file I/O +// abstract case sensitivity of underlying file system +// + +#ifndef __FSSERVICES_H +#define __FSSERVICES_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __DEBUG_H +#include "debug.h" +#endif +#ifndef __FILEERROR_H +#include "fileerror.h" +#endif + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#if IS_UNIX +#include +#endif + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +// macros for extracting the major and minor portions of int64's: +#if !defined(major) +#if !USES_GLIBC +#define major(x) ((int)((x) >> 8) & 0xff) +#define minor(x) ((int)((x) & 0xff)) +#else +#ifdef WORDS_BIGENDIAN +#define major(x) (int)(((char*)&(x))[2]) +#define minor(x) (int)(((char*)&(x))[3]) +#else +#define major(x) (int)(((char*)&(x))[1]) +#define minor(x) (int)(((char*)&(x))[0]) +#endif +#endif +#endif /* !major */ + +//========================================================================= +// TYPEDEFS +//========================================================================= + +typedef int64 cFSTime; +typedef int64 cFSType; + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +// filesystem access control lists +// it is the union of MAX(elem) for all the file systems that we support +class cACLElem { + // TODO this is just a place holder + uint32 mUid; +}; + +// this class is used only to pass arguments to iFSServices +// it is the union of MAX(elem) for all the file systems that we support +struct cFSStatArgs { + enum FileType { + TY_INVALID, // lazy evaluation + TY_FILE, + TY_DIR, + TY_BLOCKDEV, + TY_CHARDEV, + TY_SYMLINK, + TY_FIFO, + TY_SOCK + }; + + // attr is fs dependent? + uint64 dev; // dep + int64 ino; // dep + int64 mode; // dep + int64 nlink; // indep + int64 uid; // dep + int64 gid; // dep + uint64 rdev; // dep + int64 size; // indep + cFSTime atime; // indep + cFSTime mtime; // indep + cFSTime ctime; // indep + int64 blksize; // indep + int64 blocks; // dep + int64 fstype; // dep + TSTRING usid; // dep + TSTRING gsid; // dep +// int64 mFileType; // Matt's addition... + + FileType mFileType; // redundant with other information in this struct, but + // broken out for convenience + + // access control list should go here, too + std::list mACL; // indep +}; + + + +//========================================================================= +// +// eFSServices -- exception class +// +//========================================================================= + +TSS_FILE_EXCEPTION( eFSServices, eFileError ); +TSS_FILE_EXCEPTION( eFSServicesGeneric, eFSServices ); + +//========================================================================= +// +// iFSServices -- abstracts all file system calls, except for opening, reading, +// and writing, which will be handled by standard c++. +// NOTE -- all paths returned from this class will be delimited with a '/' +// +//========================================================================= + +class iFSServices +{ + public: + + /////////////////////////////////////////////////////////////// + // ENUMS + /////////////////////////////////////////////////////////////// + + //////////////////////////////////////// + // file creation modes + //////////////////////////////////////// + enum Mode + { + MODE_DEFAULT = 0, + MODE_READ = 1, + MODE_WRITE = 2, + MODE_SHARE_DELETE = 4, + MODE_SHARE_READ = 8, + MODE_SHARE_WRITE = 16, + MODE_CREATE_EXCL = 32, + MODE_CREATE_TRUNCATE = 64 + }; + + //////////////////////////////////////// + // maximum path length on platform + //////////////////////////////////////// + enum + { +#if IS_UNIX + TW_MAX_PATH = MAXPATHLEN +#endif + }; + + /////////////////////////////////////////////////////////////// + // MEMBER FUNCTIONS + /////////////////////////////////////////////////////////////// + + + //////////////////////////////////////// + // platform specific functions + //////////////////////////////////////// + virtual bool IsCaseSensitive() const = 0; + // returns true if the file system is case sensitive + virtual TCHAR GetPathSeperator() const = 0; + // returns "/" for unix and "\\" for win32 + virtual TCHAR* GetStandardBackupExtension() const = 0; + // returns normal string to append to backup files for this os. + + //////////////////////////////////////// + // process functions + //////////////////////////////////////// + virtual void Sleep( int nSeconds ) const = 0; + // makes the current process sleep for the specified number of seconds + + + //////////////////////////////////////// + // major filesystem functions + //////////////////////////////////////// + virtual void Stat( const TSTRING& strFileName, cFSStatArgs& pStat ) const throw( eFSServices ) = 0; + // fills out the cFSStatArgs structure with the stat info for the named file + virtual void GetTempDirName( TSTRING& strName ) const throw( eFSServices ) = 0; + // makes directory if it doesn't exist already. Dirname will end with a delimiter ( '/' ) + + virtual void SetTempDirName( TSTRING& tmpName ) = 0; + + virtual TSTRING& MakeTempFilename( TSTRING& strName ) const throw( eFSServices ) = 0; + // create temporary file + // TSTRING must have the form ("baseXXXXXX"), where the X's are replaced with + // characters to make it a unique file. There must be at least 6 Xs. + + // TODO: remove this function + // Matt theorized that this is no longer used - dmb Aug 23 1999 + // virtual int CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const = 0; + // creates a temporary file to which only the current process has read or write access. + // returns an open C file descriptor on success and -1 on error. Returns error if filename already exists on the filesystem. + // the file will automatically be deleted when the file descriptor is closed. + // perm should be zero or more of: + // O_WRONLY: create with read write only permission + // O_RDWR: create with read and write permission + + + //////////////////////////////////////// + // minor filesystem functions + //////////////////////////////////////// + virtual void GetHostID( TSTRING& name ) const = 0; + + virtual void GetMachineName( TSTRING& name ) const throw(eFSServices) = 0; + + virtual void GetMachineNameFullyQualified( TSTRING& name ) const = 0; + + virtual bool GetCurrentUserName( TSTRING& tstrName ) const = 0; + + virtual bool GetIPAddress( uint32& uiIPAddress ) = 0; + + + //////////////////////////////////////// + // directory specific functions + //////////////////////////////////////// + virtual void ReadDir( const TSTRING& strName, std::vector &vDirContents, bool bFullPaths = true ) const throw( eFSServices ) = 0; + // puts the contents of the specified directory, except for . and .., into the supplied vector. + // if bFullPaths is true, then the vector contains fully qualified path names; otherwise, it only contains the + // short names. + virtual void GetCurrentDir( TSTRING& strCurDir ) const throw( eFSServices ) = 0; + // returns the current working directory + virtual void ChangeDir( const TSTRING& strName ) const throw( eFSServices ) = 0; + // sets the current working directory + virtual void Mkdir( const TSTRING& strName ) const throw( eFSServices ) = 0; + + virtual bool Rmdir( const TSTRING& strName ) const = 0; + + + //////////////////////////////////////// + // file specific functions + //////////////////////////////////////// + virtual bool FileDelete( const TSTRING& name ) const = 0; + + + //////////////////////////////////////// + // directory and file functions + //////////////////////////////////////// + virtual bool Rename( const TSTRING& strOldName, const TSTRING& strNewName, bool fOverWrite = true ) const = 0; + // rename a file + virtual bool GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const = 0; + + virtual bool GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tstrGroup ) const = 0; + + + //////////////////////////////////////// + // miscellaneous utility functions + //////////////////////////////////////// + virtual void ConvertModeToString( uint64 perm, TSTRING& tstrPerm ) const = 0; + // takes a int64 permission (from stat) and changes it to look like UNIX's 'ls -l' (e.g. drwxrwxrwx) + virtual bool FullPath( TSTRING& fullPath, const TSTRING& relPath, const TSTRING& pathRelFrom = _T("") ) const = 0; + // converts relPath into a fully qualified path, storing it in FullPath. If this + // fails, false is returned. if the path to which relPath is relative is not CWD, put it in pathRelFrom. + // TODO: In some places we have depended on the behaviour that if relPath.empty() == true then we + // fail or return an empty string. Should we add this behaviour to the interface? + virtual bool GetExecutableFilename( TSTRING& strFullPath, const TSTRING& strFilename ) const = 0; + // get the path to the current executable file + virtual bool IsRoot( const TSTRING& strPath ) const = 0; + // returns true if strPath denotes a root path + + + //////////////////////////////////////// + // error functions + //////////////////////////////////////// + virtual TSTRING GetErrString() const = 0; + // Returns an error string that is appropriate for the system, (e.g. errorstr(errno) + // on UNIX and FormatError( ..., GetLastError(), ...) in Win32 + // Call this immediately after a failed system call to get a string + // representation of the error event. + + + //////////////////////////////////////// + // singleton manipulation + //////////////////////////////////////// + static iFSServices* GetInstance(); + static void SetInstance( iFSServices* pInst ); + + + /////////////////////////////////////////////////////////////// + // PRIVATE DATA + /////////////////////////////////////////////////////////////// + private: + static iFSServices* mpInstance; + + //virtual cFSStatArgs::FileType GetFileType(const cFCOName &filename) throw(eFSServices) = 0; + // returns the type of the file specified by filename. Separated from Stat() for convenience + // and potential efficiency (if a file system doesn't need to do a stat to get the file type) + + //virtual char*& MakeTempFile( char*& name) throw(eFSServices) = 0; + //virtual wchar_t*& MakeTempFile( wchar_t*& name) throw(eFSServices) = 0; + + // + // file ops + // + // these are commented out for timeliness reasons; we should uncomment and implement as needed... + // -- mdb + /* + virtual int Create(cFSName &name, Mode mode = MODE_DEFAULT) = 0; + virtual bool Mkdir(cFSName &name, Mode mode = MODE_DEFAULT) = 0; + virtual bool Delete(cFSName &name) = 0; + virtual bool Link(cFSName &src, cFSName &dest) = 0; + + virtual bool Chmod(cFSName &name, Mode mode) = 0; + virtual Mode Umask(Mode mode) = 0; + // file system types (e.g., "FAT", "NTFS", "UFS", "NFS") + virtual bool FSTypeAsString(cFSName &name, TSTRING &str) = 0; + // file type (e.g., "file", "symbolic link", "block device") + // TODO -- this should either be static or in another utility class, since it does not rely on the + // instance of the class (there is a global enumeration of file types; this fn should take a + // cFSStatArgs::FileType instead of a name. + virtual bool FileTypeAsString(cFSName &filename, TSTRING &str) = 0; + // TODO -- does this beling here? Is it always true that st_dev defines the file system? If not, then the + // Stat() call should add some extra piece of data that identifies the file system. + virtual bool IsSameFileSystem(cFSStatArgs &file1, cFSStatArgs &file2) = 0; + // to determine whether to recurse - musn't traverse mount points + + // capabilities + virtual bool IsUnicodeFilename(cFSName &name) = 0; + virtual bool IsACLCapable(cFSName &name) = 0; + virtual bool Is8bitFilename(cFSName &name) = 0; + */ +}; + + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= +inline iFSServices* iFSServices::GetInstance() +{ + ASSERT(mpInstance != 0); + + return mpInstance; +} + +inline void iFSServices::SetInstance( iFSServices* pInst ) +{ + mpInstance = pInst; +} + + +#endif + diff --git a/src/core/growheap.cpp b/src/core/growheap.cpp new file mode 100644 index 0000000..e1142ff --- /dev/null +++ b/src/core/growheap.cpp @@ -0,0 +1,194 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// growheap.cpp +#include "stdcore.h" +#include "growheap.h" +#include "debug.h" +#include + +//----------------------------------------------------------------------------- +// cGrowHeap_i +//----------------------------------------------------------------------------- +class cGrowHeap_i +{ +public: + class cHeap + { + public: + size_t mSize; + int8* mpData; + + cHeap( size_t size ) : mSize( size ), mpData( new int8[size] ) { ASSERT(mpData != 0); } + // Note: The above ASSERT should never occur! If the new failed we should have thrown a bad_alloc(). + }; + typedef std::vector HeapList; + + size_t mInitialSize; + size_t mGrowBy; + HeapList mHeaps; + TSTRING mName; + size_t mCurOff; + + cGrowHeap_i( size_t initialSize, size_t growBy, const TCHAR* name ); + ~cGrowHeap_i() { Clear(); } + + size_t AlignSizeRequest( size_t size, size_t alignSize ); + void* Malloc( size_t size ); + void Clear(); +}; + + +cGrowHeap_i::cGrowHeap_i( size_t initialSize, size_t growBy, const TCHAR* name ) +: mInitialSize( initialSize ), + mGrowBy ( growBy ), + mName ( name ), + mCurOff ( 0 ) +{ + // assure that initial size and growby are aligned + ASSERT( 0 == ( initialSize % BYTE_ALIGN ) ); + ASSERT( 0 == ( growBy % BYTE_ALIGN ) ); +} + +size_t cGrowHeap::TotalMemUsage() const +{ + size_t usage = 0; + for( cGrowHeap_i::HeapList::const_iterator i = mpData->mHeaps.begin(); i != mpData->mHeaps.end(); i++ ) + { + usage += i->mSize; + } + if( ! mpData->mHeaps.empty() ) + { + // take off the unused portion... + usage -= (mpData->mHeaps.back().mSize - mpData->mCurOff); + } + return usage; +} + + +void* cGrowHeap_i::Malloc( size_t size ) +{ + size = AlignSizeRequest( size, BYTE_ALIGN ); + + ASSERT( ( size > 0 ) && ( size < mGrowBy ) ); + + if( size >= mGrowBy ) + return NULL; + + if( mHeaps.empty() ) + { + mHeaps.push_back( cHeap( mInitialSize ) ); + ASSERT(mHeaps.back().mpData != 0); + mCurOff = 0; + } + + if( mCurOff + size < mHeaps.back().mSize ) + { + // we have room to add this to the current heap. + // + ASSERT(mHeaps.back().mpData); + int8* ret = mHeaps.back().mpData + mCurOff; + mCurOff += size; + + return ret; + } + else + { + mHeaps.push_back( cHeap( mGrowBy ) ); + ASSERT(mHeaps.back().mpData != 0); + mCurOff = 0; + + #ifdef _DEUBG + void* ret = Malloc( size ); + ASSERT(ret != 0); + return ret; + #else + return Malloc( size ); + #endif + } +} + +size_t cGrowHeap_i::AlignSizeRequest( size_t size, size_t alignSize ) +{ + // The two's complement algorithm requires a non-zero size request size, + // so make make all requests require it so that this function + // acts the same no matter what the integer representation + if( 0 == size ) + size = 1; + +#if USES_2S_COMPLEMENT + // This efficient algorithm assumes alignSize is power of two AND a + // 2's complement representation. Requires non-zero size request + ASSERT( 0 == ( alignSize % 2 ) ); + ASSERT( size > 0 ); + return( ( size + alignSize - 1 ) & ~( alignSize - 1 ) ); +#else + // this makes no assumption about BYTE_ALIGN or hardware integer representation + return( ( ( size / alignSize ) + ( ( size % alignSize ) ? 1 : 0 ) ) * alignSize ); +#endif +} + +void cGrowHeap_i::Clear() +{ + for( HeapList::iterator i = mHeaps.begin(); i != mHeaps.end(); i++ ) + { + delete [] i->mpData; + } + mHeaps.clear(); +} + +//----------------------------------------------------------------------------- +// cGrowHeap +//----------------------------------------------------------------------------- +cGrowHeap::cGrowHeap( size_t initialSize, size_t growBy, const TCHAR* name ) : + mpData( new cGrowHeap_i( initialSize, growBy, name ) ) +{ + +} + +cGrowHeap::~cGrowHeap() +{ + cDebug d("FCO name heap stats"); + d.TraceDebug( _T("Total heap memory usage for %s: %d\n"), mpData->mName.c_str(), TotalMemUsage() ); + + delete mpData; +} + +void* cGrowHeap::Malloc( size_t size ) +{ + return mpData->Malloc( size ); +} + +void cGrowHeap::Clear() +{ + mpData->Clear(); +} + diff --git a/src/core/growheap.h b/src/core/growheap.h new file mode 100644 index 0000000..250c58d --- /dev/null +++ b/src/core/growheap.h @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// growheap.h +// +#ifndef __GROWHEAP_H +#define __GROWHEAP_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//----------------------------------------------------------------------------- +// cGrowHeap -- a heap that can grow but never shrink +// All items alloced should be well below growBy in size +//----------------------------------------------------------------------------- +class cGrowHeap_i; + +class cGrowHeap +{ +public: + cGrowHeap( size_t initialSize, size_t growby, const TCHAR* name ); + // creates a heap that is initially initialSize big, and increases the + // size by growBy every time there is no more room. + // initialSize and growby must be a multiple of BYTE_ALIGN + ~cGrowHeap(); + + void* Malloc( size_t size ); + void Clear(); + // resets the grow heap's state. + size_t TotalMemUsage() const; + // returns the total memory usage of this heap +private: + cGrowHeap_i* mpData; +}; + + +#endif + diff --git a/src/core/growheap_t.cpp b/src/core/growheap_t.cpp new file mode 100644 index 0000000..50e07cc --- /dev/null +++ b/src/core/growheap_t.cpp @@ -0,0 +1,99 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// growheap_t.cpp +// +// test the grow heap component + +#include "stdcore.h" +#include "growheap.h" +#include "test/test.h" +#include "error.h" + +using namespace std; + +void TestGrowHeap() +{ + const int initSize = 0x4000; + const int growBy = 0x4000; + cGrowHeap gh( initSize, growBy, _T("growheap_t.cpp") ); + + // report initial state + TCOUT << _T("Initial size: ") << initSize << endl; + TCOUT << _T("Growby: ") << growBy << endl; + TCOUT << _T("Initial Growheap memory usage: ") << gh.TotalMemUsage() << endl << endl; + + const int growFactor = 5; // how much to enlarge requests each time + // make it odd so we can see if the growheap + // rounds to the alignment size + for( size_t size = 1; size < growBy; size *= growFactor ) + { + // allocate memory + TCOUT << _T("Allocing by ") << size << endl; + void* p = gh.Malloc( size ); + TEST( p != NULL ); + + // access memory with ints + if( size > sizeof(int) ) + { + // read from memory + TCOUT << _T("Reading an int from memory...") << endl; + int* pi = static_cast< int* >( p ); + int i = *pi; + + // write to memory + TCOUT << _T("Writing an int to memory...") << endl; + *pi = i; + } + + // access memory with doubles + if( size > sizeof(double) ) + { + // read from memory + TCOUT << _T("Reading a double from memory...") << endl; + double* pd = static_cast< double* >( p ); + double d = *pd; + + // write to memory + TCOUT << _T("Writing a double to memory...") << endl; + *pd = d; + } + + // report total usage + TCOUT << _T("Growheap memory usage: ") << gh.TotalMemUsage() << endl << endl; + } + + // free memory + gh.Clear(); + TEST( gh.TotalMemUsage() == 0 ); +} + diff --git a/src/core/hashtable.cpp b/src/core/hashtable.cpp new file mode 100644 index 0000000..dfe3ad6 --- /dev/null +++ b/src/core/hashtable.cpp @@ -0,0 +1,36 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//hashtable.cpp : implementation for hashtable which maps const TCHAR*'s to void*'s +#include "stdcore.h" +#include "hashtable.h" + + diff --git a/src/core/hashtable.h b/src/core/hashtable.h new file mode 100644 index 0000000..d581be0 --- /dev/null +++ b/src/core/hashtable.h @@ -0,0 +1,544 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// hashtable.h : a template class for mapping tuples using TCHAR*'s +// +// implements cHashTable, which maps a key of arbitrary type to a value +// of arbitrary type. The key data type MUST have the const byte*() +// operator overloaded in order for this to work. TSTRINGS will always +// work as the key value because of the overloaded-template-function +// +// Note: Any overloaded const byte*() operator must return an +// length of key as well. see cDefaultConvert +// +// IMPORTANT -- cDefaultConvert only works for pointers to objects +// -- cDefaultCompare only (mostly) works for objects + +#ifndef __HASHTABLE_H +#define __HASHTABLE_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __DEBUG_H +#include "debug.h" +#endif + +#ifndef __ERROR_H +#include "error.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Comparison function objects ... these are used by the hash table to determine +// equality. The one defined should work for objects that use op== to define +// equality. There is also a specialization for TSTRINGS. If neither of these +// fit your needs, you must pass the hash table your own fn pointer or class +/////////////////////////////////////////////////////////////////////////////// +template +class cDefaultCompare +{ +public: + bool operator()(const T& lhs, const T& rhs) + { + return lhs == rhs; + } +}; +///////////////////////////////////////////////////////// +// specialization for TSTRINGS +///////////////////////////////////////////////////////// +template<> +inline bool cDefaultCompare::operator()(const TSTRING& lhs, const TSTRING& rhs) +{ + return (lhs.compare(rhs) == 0); +} + +/////////////////////////////////////////////////////////////////////////////// +// Conversion function objects ... used by the hash table to locate the key in KEY_TYPE +// into a byte* and a key length (for hashing purposes). The default implementation +// just does a cast. A specialization is also provided for TSTRINGs. +/////////////////////////////////////////////////////////////////////////////// +template +class cDefaultConvert +{ +public: + const byte* operator()(const T& obj, int* const pcbKeyLen) + { + // HACK! TODO: in the interest of time, I've left this as it is..... + *pcbKeyLen = sizeof(TCHAR) * _tcslen(obj); + return (byte*)obj; + } +}; +///////////////////////////////////////////////////////// +// specialization for TSTRINGS +///////////////////////////////////////////////////////// +template<> +inline const byte* cDefaultConvert::operator()(const TSTRING& obj, int* const pcbKeyLen ) +{ + *pcbKeyLen = sizeof(TCHAR) * obj.length(); + return (byte*)obj.c_str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// cHashTable +// KEY -- the key you are hashing on +// VAL -- the value you want associated with that key +// CMP -- a function object that takes (KEY, KEY) and returns true if they +// are equal. +// CONVERTER -- function object that takes (KEY, int* pcbKeyLen) and returns a const byte* +// ( points to start of key ) and a byte length (in pcbKeyLen) that tells the hashtable +// how long the key is +/////////////////////////////////////////////////////////////////////////////// +// these were moved outside of the class because it sucks to have to name the class with template parameters +// ie -- mTable(cHashTable::MEDIUM +enum cHashTable_TableSize { + HASH_VERY_SMALL = 17, + HASH_SMALL = 2007, + HASH_MEDIUM = 6007, + HASH_LARGE = 13007, + HASH_VERY_LARGE = 49999 +}; + +// forward declaration +template , class CONVERTER = cDefaultConvert > +class cHashTableIter; + +//General version of cHashTable template: +template , class CONVERTER = cDefaultConvert > +class cHashTable +{ +friend class cHashTableIter; +public: + //structure for hash table nodes. + struct node { + KEY_TYPE nKey; + VAL_TYPE nData; + node* next; + }; + + cHashTable(int tblSize = HASH_MEDIUM); + ~cHashTable(); + + bool Insert(KEY_TYPE key, VAL_TYPE data_in); + // The pointer, data_in, is stored in a node based on string_in's hashing. + // + // if (key) already exists in the table, then it's value is replaced by (data_in) + // returns true if (key) already existed in table. otherwise, returns false + + bool Lookup(KEY_TYPE key, VAL_TYPE& data_out) const; + //bool Lookup(TSTRING key, VAL_TYPE& data_out) const; + //Lookup returns true if a match is found for string_check. A reference + //to the node in the table that matches string_check is passed back (by ref). + bool Remove(KEY_TYPE key); + //The node that matches string_out is de-allocated. + + bool Clear(void); + //Clears the entire table and sets all node pointers to NULL + bool IsEmpty(void) const; + uint32 Hash( const KEY_TYPE& key ) const; + //The hashing function, taken from old Tripwire + int32 GetNumValues() const { return mValuesInTable; }; + // returns number of table entries filled + +#ifdef _DEBUG + void TraceDiagnostics() const; + // traces hash table statistics +#endif + +private: + cHashTable(const cHashTable& rhs); // not impl + void operator=(const cHashTable& rhs); // not impl + + node** mTable; + int mTableSize; + int32 mValuesInTable; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cHashTableIter +/////////////////////////////////////////////////////////////////////////////// + +template +class cHashTableIter +{ +public: + cHashTableIter(const cHashTable& hashTbl); + + void SeekBegin() const; + bool Done() const; + void Next() const; + + const KEY_TYPE& Key() const; + const VAL_TYPE& Val() const; + VAL_TYPE& Val(); + +private: + mutable int mCurIndex; + mutable typename cHashTable::node* mpCurNode; + const cHashTable& mHashTable; + + // helper function + void SeekNextValid() const; +}; + + + +//############################################################################# +// implementation + +/////////////////////////////////////////////////////////////////////////////// +// iterator +/////////////////////////////////////////////////////////////////////////////// +template +inline cHashTableIter::cHashTableIter( const cHashTable& hashTbl) : + mHashTable(hashTbl) +{ + SeekBegin(); +} + +template +inline void cHashTableIter::SeekBegin() const +{ + mCurIndex = 0; + mpCurNode = mHashTable.mTable[0]; + if(! mpCurNode) + SeekNextValid(); +} + +template +inline bool cHashTableIter::Done() const +{ + return ((mCurIndex < 0) || (mCurIndex >= mHashTable.mTableSize)); +} + +template +inline void cHashTableIter::Next() const +{ + SeekNextValid(); +} + +template +inline void cHashTableIter::SeekNextValid() const +{ + if(mpCurNode) + mpCurNode = mpCurNode->next; + //mCurIndex++; + while((! mpCurNode) && (mCurIndex < mHashTable.mTableSize)) + { + mpCurNode = mHashTable.mTable[++mCurIndex]; + } +} + +template +inline const KEY_TYPE& cHashTableIter::Key() const +{ + ASSERT(! Done()); + return mpCurNode->nKey; +} +template +inline const VAL_TYPE& cHashTableIter::Val() const +{ + ASSERT(! Done()); + return mpCurNode->nData; +} +template +inline VAL_TYPE& cHashTableIter::Val() +{ + ASSERT(! Done()); + return mpCurNode->nData; +} + +/////////////////////////////////////////////////////////////////////////////// +// Constructors & Destructor +/////////////////////////////////////////////////////////////////////////////// + +//Default value for tblSize == 6007 +template +cHashTable::cHashTable(int tblSize) +{ + mValuesInTable = 0; + mTableSize = tblSize; + mTable = new node*[mTableSize]; + + for (int i=0; i < mTableSize; ++i) + mTable[i] = NULL; +} + +//Destructor steps through table and deallocates all dynamic memory +template +cHashTable::~cHashTable() +{ + for (int i=0; inext; + + delete del; + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Insert -- Hashes a const TCHAR* to a new index. Collisions are resolved +// using seperate chaining (link lists). +//////////////////////////////////////////////////////////////////////////////// +// General Version: +template +bool cHashTable::Insert(KEY_TYPE key, VAL_TYPE d_in) +{ + COMPARE_OP compare; + + int hindex = Hash( key ); + if (mTable[hindex] == NULL) { + //open index, perform insert + mTable[hindex] = new node; + (mTable[hindex])->nKey = key; + (mTable[hindex])->next = NULL; + (mTable[hindex])->nData = d_in; + mValuesInTable++; + + return false; + } + else //collision, do linked list insert + { + // case 1: key already exists in list -- replace existing one + // case 2: key does not exist -- add to end of list + + node* nodeptr = mTable[hindex]; + + bool found = false; + while (true) + { + if ( compare(nodeptr->nKey, key)) + { + // we found a duplicate! + found = true; + break; + } + + // break if this is the last node in the list + if(! nodeptr->next) + break; + + // otherwise, keep traversing + nodeptr = nodeptr->next; + } + + // add a node if the key was not found + if (! found) + { + node *prev = nodeptr; + nodeptr = new node; + nodeptr->nKey = key; + nodeptr->next = NULL; + prev->next = nodeptr; + + mValuesInTable++; + } + + // whether it is a new node or not, set the data to this new value + nodeptr->nData = d_in; + + return found; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Lookup -- Attempts to find 'string' in the hash table. +//////////////////////////////////////////////////////////////////////////////// +// General Version: +template +bool +cHashTable::Lookup(KEY_TYPE key, VAL_TYPE& d_out) const +{ + COMPARE_OP compare; + + int hindex = Hash( key ); + if (mTable[hindex] == NULL) + return false; + else { + node* nodeptr = mTable[hindex]; + while (nodeptr != NULL) + { + if( compare(nodeptr->nKey, key)) { + d_out = nodeptr->nData; + return true; + } + nodeptr = nodeptr->next; + } + } + return false; //mTable entries exhausted without a match +} + +//////////////////////////////////////////////////////////////////////////////// +// Remove -- Removes a single entry from the hash table. Returns false if +// the nKey is not found in the table. +//////////////////////////////////////////////////////////////////////////////// +// General Version - +template +bool +cHashTable::Remove(KEY_TYPE key) +{ + COMPARE_OP compare; + + int hindex = Hash( key ); + if (mTable[hindex] == NULL) { + delete (mTable[hindex]); + mTable[hindex] = NULL; + return true; + } + else { + node* nodeptr = mTable[hindex]; + node* prev; + while(nodeptr != NULL) { + prev = nodeptr; + if(compare(mTable[hindex]->nKey, key)) + { + prev->next = nodeptr->next; + delete nodeptr; + if (nodeptr == mTable[hindex]) + mTable[hindex] = NULL; + nodeptr = NULL; + return true; + }//end if + nodeptr = nodeptr->next; + }//end while + }//end else + return false; //match was not found, no node deleted +} + +//////////////////////////////////////////////////////////////////////////////// +// Clear -- Clears entire hash table so that all indices are NULL +//////////////////////////////////////////////////////////////////////////////// +template +bool +cHashTable::Clear(void) +{ + for (int i=0; inext; + delete del; + if (del == mTable[i]) + mTable[i] = NULL; + del = NULL; + + }//end delete chain loop + }//end if mTable[i]!= NULL + }//end for + return (IsEmpty()); +} + +//////////////////////////////////////////////////////////////////////////////// +// IsEmpty -- +//////////////////////////////////////////////////////////////////////////////// +template +bool +cHashTable::IsEmpty(void) const +{ + bool ret = true; + for(int i=0; i< mTableSize; ++i) + ret &= (mTable[i] == NULL); + return ret; +} + +//////////////////////////////////////////////////////////////////////////////// +// Hash -- performs hashing on key, returns an integer index val. +//////////////////////////////////////////////////////////////////////////////// +template +uint32 cHashTable::Hash( const KEY_TYPE& key ) const +{ + CONVERTER converter; + int len; + const byte* pb = converter( key, &len ); //locates key + uint32 hindex; + + hindex = *pb; + while (len-- > 0) + hindex = ((hindex << 9) ^ *pb++) % mTableSize; + return hindex; +} + +#ifdef _DEBUG + +template +void cHashTable::TraceDiagnostics() const +{ + cDebug d("cHashTable::Diagnostics"); + + int slotsFilled = 0, numItems = 0, numMultiSlot = 0; + node* pNode; + + for(int i=0; i < mTableSize; i++) + { + if(mTable[i] != NULL) + { + slotsFilled++; + numItems++; + pNode = (mTable[i])->next; + if(pNode != NULL) + numMultiSlot++; + while(pNode) + { + numItems++; + pNode = pNode->next; + } + } + } + + d.TraceDebug("---------------Hash Table Statisics---------------\n"); + d.TraceDebug("-- Number of slots: %d\n", mTableSize); + d.TraceDebug("-- Number of items: %d\n", numItems); + d.TraceDebug("-- Slots filled: %d (%lf %%)\n",slotsFilled, ((double)slotsFilled / (double)mTableSize) * 100.0); + d.TraceDebug("-- Slots with >1 item: %d (%lf %%)\n",numMultiSlot, ((double)numMultiSlot / (double)slotsFilled) * 100.0); + d.TraceDebug("--------------------------------------------------\n"); +} +#endif // _DEBUG + + +#endif //__HASHTABLE_H + diff --git a/src/core/hashtable_t.cpp b/src/core/hashtable_t.cpp new file mode 100644 index 0000000..b07affe --- /dev/null +++ b/src/core/hashtable_t.cpp @@ -0,0 +1,220 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//hashtable_t.cpp : Test suite for cHashTable. + +#include "stdcore.h" +#include "hashtable.h" +#include + +#ifndef __TEST_H +#include "test/test.h" +#endif + +//#include "dummy.h" + +using namespace std; + +void HashTest1(); +void HashTest2(); + +void TestHashTable(void) +{ + HashTest1(); + HashTest2(); +} + +void HashTest1() +{ + //Test the Hash table with Key = TSTRING + + cHashTable htable; + cDebug d("TestHashTable()::Test1"); + d.TraceDetail("Entering ...\n"); + + //return val for all function calls. + bool ret = true; + + //test data + TSTRING string = _T("test string"); + TSTRING string2 = _T("another test string"); + TSTRING string3 = _T("yet another test string"); + void* data_ptr = NULL; + void* data_ptr2 = NULL; + void* data_ptr3 = NULL; + void* test_lookup = NULL; + + int var = 32; + int var2 = 33; + int* test = &var; + int* test2 = &var2; + + data_ptr = test; + data_ptr2 = test2; + + //Test insert and lookup. + htable.Insert(string, data_ptr); + ret &= htable.Lookup(string, test_lookup); + TEST(ret); + + //Make sure value is being stored and returned correctly + d.TraceDetail("Value returned from table is %i, and should be %i.\n", *((int*)test_lookup), var); + TEST(*((int*)test_lookup) == var); + + //Check remove and lookup (lookup should fail) + ret &= htable.Remove(string); + TEST(ret); + ret &= !htable.Lookup(string, test_lookup); + TEST(ret); + //Has test_lookup's value changed? It shouldn't have... + TEST(*((int*)test_lookup) == var); + + //Insert and Remove different string/key combo. + htable.Insert(string2, data_ptr2); + htable.Insert(string3, data_ptr3); + + // test iteration + cHashTableIter iter(htable); + d.TraceDebug("Testing the iterator:\n"); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + d.TraceDebug(_T("Key=%s\tValue=%d\n"), iter.Key().c_str(), iter.Val()); + } + + // get statistics +#ifdef _DEBUG + htable.TraceDiagnostics(); +#endif + + //Test IsEmpty() + ret &= !htable.IsEmpty(); + TEST(!htable.IsEmpty()); + + //Test Clear(), IsEmpty() + ret &= htable.Clear(); + TEST(htable.Clear()); + ret &= htable.IsEmpty(); + TEST(htable.IsEmpty()); +/* + //Test the Hash table with arbitrary key + + + //Won't work with int!! (oops). I'll need to make one of our data types + // const TCHAR*() capable. Casting an int to a TCHAR* just returns an address, + // so there's no way to properly hash (no length, etc). + cHashTable htable2; + cDummy key1, key2; + key1.SetInt(40); + key2.SetInt(50); + test_lookup = NULL; + + //Test insert and lookup. + htable2.Insert(key1, data_ptr); + TEST(ret &= htable2.Lookup(key1, test_lookup)); + + //Make sure value is being stored and returned correctly + d.TraceDetail("Value returned from table is %i, and should be %i.\n", *((int*)test_lookup), var); + TEST(*((int*)test_lookup) == var); + + //Check remove and lookup (lookup should fail) + TEST(ret &= htable2.Remove(key1)); + TEST(ret &= !htable2.Lookup(key1, test_lookup)); + //Has test_lookup's value changed? It shouldn't have... + TEST(*((int*)test_lookup) == var); + + //Insert and different key/val combo. + htable2.Insert(key2, data_ptr2); + + //Test IsEmpty() + ret &= !htable2.IsEmpty(); + TEST(!htable2.IsEmpty()); + + //Test Clear(), IsEmpty() + ret &= htable2.Clear(); + TEST(htable2.Clear()); + ret &= htable2.IsEmpty(); + TEST(htable2.IsEmpty()); + +*/ + return; +} + +void HashTest2() +{ + cDebug d("TestHashTable()::Test2"); + d.TraceDebug("entering...\n"); + + { + cHashTable tbl; + + // test insert and lookup + TEST(tbl.Insert(_T("foo"), _T("foo")) == false); + + TSTRING val; + TEST(tbl.Lookup(_T("foo"), val)); + TEST(val.compare(_T("foo")) == 0); + + // check Empty() on non-empty list + TEST(tbl.IsEmpty() == false); + + // test insertion with collision + TEST(tbl.Insert(_T("foo"), _T("bar")) == true); + TEST(tbl.Lookup(_T("foo"), val)); + TEST(val.compare(_T("bar")) == 0); + + // test removal + TEST(tbl.Remove(_T("foo"))); + + // make sure it's totally empty (confirms that hash table insertion worked!) + TEST(tbl.IsEmpty()); + + // test another insertion + TEST(tbl.Insert(_T("a"), _T("bcd")) == false); + TEST(tbl.Insert(_T("b"), _T("def")) == false); + + TSTRING v1, v2; + TEST(tbl.Lookup(_T("a"), v1)); + TEST(tbl.Lookup(_T("b"), v2)); + + TEST(v1.compare(_T("bcd")) == 0); + TEST(v2.compare(_T("def")) == 0); + + // remove and test IsEmpty() + TEST(tbl.Remove(_T("a"))); + TEST(tbl.IsEmpty() == false); + + TEST(tbl.Remove(_T("b"))); + TEST(tbl.IsEmpty() == true); + + } + + d.TraceDebug("PASSED!\n"); +} diff --git a/src/core/haval.cpp b/src/core/haval.cpp new file mode 100644 index 0000000..3a10bbb --- /dev/null +++ b/src/core/haval.cpp @@ -0,0 +1,744 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* + * haval.c: specifies the routines in the HAVAL (V.1) hashing library. + * + * HAVAL is a one-way hashing algorithm with the following + * collision-resistant property: + * It is computationally infeasible to find two or more + * messages that are hashed into the same fingerprint. + * + * Reference: + * Y. Zheng, J. Pieprzyk and J. Seberry: + * ``HAVAL --- a one-way hashing algorithm with variable + * length of output'', Advances in Cryptology --- AUSCRYPT'92, + * Lecture Notes in Computer Science, Springer-Verlag, 1993. + * + * Descriptions: + * - haval_string: hash a string + * - haval_file: hash a file + * - haval_stdin: filter -- hash input from the stdin device + * - haval_hash: hash a string of specified length + * (Haval_hash is used in conjunction with + * haval_start & haval_end.) + * - haval_hash_block: hash a 32-word block + * - haval_start: initialization + * - haval_end: finalization + * + * Author: Yuliang Zheng + * Department of Computer Science + * University of Wollongong + * Wollongong, NSW 2522, Australia + * Email: yuliang@cs.uow.edu.au + * Voice: +61 42 21 4331 (office) + * + * Date: June 1993 + * + * Copyright (C) 1993 by C^3SR. All rights reserved. + * This program may not be sold or used as inducement to + * buy a product without the written permission of C^3SR. + */ + +/* + * Some comments on getting Haval into Tripwire: + * + * - all #elif directives replaced by ugly #if/#else/#endif sequences. + * not all compilers support #elif (an ANSI construct). + * - byte-order is discovered at compile time. we use the information + * in "../../include/byteorder.h" to get this information. + */ +#include "stdcore.h" +#include +#include +#include "haval.h" +#include "debug.h" + +#define HAVAL_VERSION 1 /* current version number */ + +/* Do not remove this line. Protyping depends on it! */ +#if defined(__STDC__) || defined(__cplusplus) +#define P_(s) s +#else +#define P_(s) () +#endif + +void haval_string P_((char *, uint8 *)); /* hash a string */ +int haval_file P_((char *, uint8 *)); /* hash a file */ +void haval_stdin P_((void)); /* hash input from stdin */ +void haval_start P_((haval_state *)); /* initialization */ +void haval_hash P_((haval_state *, + uint8 *, int)); /* updating routine */ +void haval_end P_((haval_state *, uint8 *)); /* finalization */ +void haval_hash_block P_((haval_state *)); /* hash a 32-word block */ +static void haval_tailor P_((haval_state *)); /* folding the last output */ + +static uint8 padding[128] = { /* constants for padding */ +0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#define f_1(x6, x5, x4, x3, x2, x1, x0) \ + ((x1) & ((x0) ^ (x4)) ^ (x2) & (x5) ^ \ + (x3) & (x6) ^ (x0)) + +#define f_2(x6, x5, x4, x3, x2, x1, x0) \ + ((x2) & ((x1) & ~(x3) ^ (x4) & (x5) ^ (x6) ^ (x0)) ^ \ + (x4) & ((x1) ^ (x5)) ^ (x3) & (x5) ^ (x0)) + +#define f_3(x6, x5, x4, x3, x2, x1, x0) \ + ((x3) & ((x1) & (x2) ^ (x6) ^ (x0)) ^ \ + (x1) & (x4) ^ (x2) & (x5) ^ (x0)) + +#define f_4(x6, x5, x4, x3, x2, x1, x0) \ + ((x4) & ((x5) & ~(x2) ^ (x3) & ~(x6) ^ (x1) ^ (x6) ^ (x0)) ^ \ + (x3) & ((x1) & (x2) ^ (x5) ^ (x6)) ^ \ + (x2) & (x6) ^ (x0)) + +#define f_5(x6, x5, x4, x3, x2, x1, x0) \ + ((x0) & ((x1) & (x2) & (x3) ^ ~(x5)) ^ \ + (x1) & (x4) ^ (x2) & (x5) ^ (x3) & (x6)) + +/* + * Permutations phi_{i,j}, i=3,4,5, j=1,...,i. + * + * PASS = 3: + * 6 5 4 3 2 1 0 + * | | | | | | | (replaced by) + * phi_{3,1}: 1 0 3 5 6 2 4 + * phi_{3,2}: 4 2 1 0 5 3 6 + * phi_{3,3}: 6 1 2 3 4 5 0 + * + * PASS = 4: + * 6 5 4 3 2 1 0 + * | | | | | | | (replaced by) + * phi_{4,1}: 2 6 1 4 5 3 0 + * phi_{4,2}: 3 5 2 0 1 6 4 + * phi_{4,3}: 1 4 3 6 0 2 5 + * phi_{4,4}: 6 4 0 5 2 1 3 + * + * PASS = 5: + * 6 5 4 3 2 1 0 + * | | | | | | | (replaced by) + * phi_{5,1}: 3 4 1 0 5 2 6 + * phi_{5,2}: 6 2 1 0 3 4 5 + * phi_{5,3}: 2 6 0 4 3 1 5 + * phi_{5,4}: 1 5 3 2 0 4 6 + * phi_{5,5}: 2 5 0 6 4 3 1 + */ + +#if PASS == 3 +# define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \ + f_1(x1, x0, x3, x5, x6, x2, x4) +#else +# if PASS == 4 +# define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \ + f_1(x2, x6, x1, x4, x5, x3, x0) +# else +# define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \ + f_1(x3, x4, x1, x0, x5, x2, x6) +# endif +#endif + +#if PASS == 3 +# define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \ + f_2(x4, x2, x1, x0, x5, x3, x6) +#else +# if PASS == 4 +# define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \ + f_2(x3, x5, x2, x0, x1, x6, x4) +# else +# define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \ + f_2(x6, x2, x1, x0, x3, x4, x5) +# endif +#endif + +#if PASS == 3 +# define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \ + f_3(x6, x1, x2, x3, x4, x5, x0) +#else +# if PASS == 4 +# define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \ + f_3(x1, x4, x3, x6, x0, x2, x5) +# else +# define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \ + f_3(x2, x6, x0, x4, x3, x1, x5) +# endif +#endif + +#if PASS == 4 +# define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \ + f_4(x6, x4, x0, x5, x2, x1, x3) +#else +# define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \ + f_4(x1, x5, x3, x2, x0, x4, x6) +#endif + +#define Fphi_5(x6, x5, x4, x3, x2, x1, x0) \ + f_5(x2, x5, x0, x6, x4, x3, x1) + +#define rotate_right(x, n) (((x) >> (n)) | ((x) << (32-(n)))) + +#define FF_1(x7, x6, x5, x4, x3, x2, x1, x0, w) { \ + register haval_word temp = Fphi_1(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w); \ + } + +#define FF_2(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \ + register haval_word temp = Fphi_2(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \ + } + +#define FF_3(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \ + register haval_word temp = Fphi_3(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \ + } + +#define FF_4(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \ + register haval_word temp = Fphi_4(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \ + } + +#define FF_5(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \ + register haval_word temp = Fphi_5(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \ + } + +/* + * translate every four characters into a word. + * assume the number of characters is a multiple of four. + */ +#define ch2uint(string, word, slen) { \ + uint8 *sp = string; \ + haval_word *wp = word; \ + while (sp < (string) + (slen)) { \ + *wp++ = (haval_word)*sp | \ + ((haval_word)*(sp+1) << 8) | \ + ((haval_word)*(sp+2) << 16) | \ + ((haval_word)*(sp+3) << 24); \ + sp += 4; \ + } \ +} + +/* translate each word into four characters */ +#define uint2ch(word, string, wlen) { \ + haval_word *wp = word; \ + uint8 *sp = string; \ + while (wp < (word) + (wlen)) { \ + *(sp++) = (uint8)( *wp & 0xFF); \ + *(sp++) = (uint8)((*wp >> 8) & 0xFF); \ + *(sp++) = (uint8)((*wp >> 16) & 0xFF); \ + *(sp++) = (uint8)((*wp >> 24) & 0xFF); \ + wp++; \ + } \ +} + + +/* hash a string */ +void haval_string (char *string, uint8 fingerprint[FPTLEN >> 3]) +{ + haval_state state; + unsigned int len = strlen (string); + + haval_start (&state); + haval_hash (&state, (uint8 *)string, len); + haval_end (&state, fingerprint); +} + +/* hash a file */ +int haval_file (char* file_name, uint8 fingerprint[FPTLEN >> 3]) +{ + FILE *file; + haval_state state; + int len; + uint8 buffer[1024]; + + if ((file = fopen (file_name, "rb")) == NULL) + { + return (1); /* fail */ + } + else + { + haval_start (&state); + while ( len = fread (buffer, 1, 1024, file), len != 0 ) + { + haval_hash (&state, buffer, len); + } + fclose (file); + haval_end (&state, fingerprint); + return (0); /* success */ + } +} + +/* hash input from stdin */ +void haval_stdin () +{ + haval_state state; + int i, len; + uint8 buffer[32], + fingerprint[FPTLEN >> 3]; + + haval_start (&state); + while ( len = fread (buffer, 1, 32, stdin), len != 0 ) { + haval_hash (&state, buffer, len); + } + haval_end (&state, fingerprint); + + for (i = 0; i < FPTLEN >> 3; i++) { + putchar(fingerprint[i]); + } +} + +/* initialization */ +void haval_start (haval_state *state) +{ + state->count[0] = state->count[1] = 0; /* clear count */ + state->fingerprint[0] = 0x243F6A88; /* initial fingerprint */ + state->fingerprint[1] = 0x85A308D3; + state->fingerprint[2] = 0x13198A2E; + state->fingerprint[3] = 0x03707344; + state->fingerprint[4] = 0xA4093822; + state->fingerprint[5] = 0x299F31D0; + state->fingerprint[6] = 0x082EFA98; + state->fingerprint[7] = 0xEC4E6C89; +} + +/* + * hash a string of specified length. + * to be used in conjunction with haval_start and haval_end. + */ +void haval_hash (haval_state* state, uint8* str, int str_len) +{ + ASSERT(str_len >= 0); + + unsigned int i, + rmd_len, + fill_len; + + /* calculate the number of bytes in the remainder */ + rmd_len = (unsigned int)((state->count[0] >> 3) & 0x7F); + fill_len = 128 - rmd_len; + + /* update the number of bits */ + if ((state->count[0] += (haval_word)str_len << 3) + < ((haval_word)str_len << 3)) { + state->count[1]++; + } + state->count[1] += (haval_word)str_len >> 29; + +#if BYTEORDER == 0x1234 + + /* hash as many blocks as possible */ + if (rmd_len + str_len >= 128) { + memcpy (((uint8 *)state->block)+rmd_len, str, fill_len); + haval_hash_block (state); + for (i = fill_len; i + 127 < str_len; i += 128){ + memcpy ((uint8 *)state->block, str+i, 128); + haval_hash_block (state); + } + rmd_len = 0; + } else { + i = 0; + } + memcpy (((uint8 *)state->block)+rmd_len, str+i, str_len-i); + +#else + + /* hash as many blocks as possible */ + if (rmd_len + str_len >= 128) { + memcpy ((char*) &state->remainder[rmd_len], (char*) str, fill_len); + ch2uint(state->remainder, state->block, 128); + haval_hash_block (state); + for (i = fill_len; i + 127 < (unsigned int)str_len; i += 128){ + memcpy ((char *) state->remainder, (char *) str+i, 128); + ch2uint(state->remainder, state->block, 128); + haval_hash_block (state); + } + rmd_len = 0; + } else { + i = 0; + } + /* save the remaining input chars */ + memcpy ((char *) &state->remainder[rmd_len], (char *) str+i, str_len-i); + +#endif +} + +/* finalization */ +void haval_end (haval_state* state, uint8 final_fpt[FPTLEN >> 3]) +{ + uint8 tail[10]; + unsigned int rmd_len, pad_len; + + /* + * save the version number, the number of passes, the fingerprint + * length and the number of bits in the unpadded message. + */ + tail[0] = (uint8)(((FPTLEN & 0x3) << 6) | + ((PASS & 0x7) << 3) | + (HAVAL_VERSION & 0x7)); + tail[1] = (uint8)((FPTLEN >> 2) & 0xFF); + uint2ch (state->count, &tail[2], 2); + + /* pad out to 118 mod 128 */ + rmd_len = (unsigned int)((state->count[0] >> 3) & 0x7f); + pad_len = (rmd_len < 118) ? (118 - rmd_len) : (246 - rmd_len); + haval_hash (state, padding, pad_len); + + /* + * append the version number, the number of passes, + * the fingerprint length and the number of bits + */ + haval_hash (state, tail, 10); + + /* tailor the last output */ + haval_tailor(state); + + /* translate and save the final fingerprint */ + uint2ch (state->fingerprint, final_fpt, FPTLEN >> 5); + + /* clear the state information */ + memset ((char *)state, 0, sizeof (*state)); +} + +/* hash a 32-word block */ +void haval_hash_block (haval_state* state) +{ + register haval_word t0 = state->fingerprint[0], /* make use of */ + t1 = state->fingerprint[1], /* internal registers */ + t2 = state->fingerprint[2], + t3 = state->fingerprint[3], + t4 = state->fingerprint[4], + t5 = state->fingerprint[5], + t6 = state->fingerprint[6], + t7 = state->fingerprint[7], + *w = state->block; + + /* Pass 1 */ + FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w )); + FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 1)); + FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 2)); + FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3)); + FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4)); + FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 5)); + FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 6)); + FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 7)); + + FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 8)); + FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9)); + FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+10)); + FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+11)); + FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+12)); + FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+13)); + FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+14)); + FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15)); + + FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+16)); + FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+17)); + FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+18)); + FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+19)); + FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+20)); + FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+21)); + FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+22)); + FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23)); + + FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24)); + FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+25)); + FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26)); + FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+27)); + FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28)); + FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+29)); + FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+30)); + FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+31)); + + /* Pass 2 */ + FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x452821E6); + FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0x38D01377); + FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26), 0xBE5466CF); + FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+18), 0x34E90C6C); + FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+11), 0xC0AC29B7); + FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+28), 0xC97C50DD); + FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 7), 0x3F84D5B5); + FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+16), 0xB5470917); + + FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w ), 0x9216D5D9); + FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0x8979FB1B); + FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+20), 0xD1310BA6); + FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0x98DFB5AC); + FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0x2FFD72DB); + FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xD01ADFB7); + FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 4), 0xB8E1AFED); + FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 8), 0x6A267E96); + + FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+30), 0xBA7C9045); + FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0xF12C7F99); + FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x24A19947); + FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 9), 0xB3916CF7); + FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x0801F2E2); + FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+24), 0x858EFC16); + FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+29), 0x636920D8); + FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 6), 0x71574E69); + + FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0xA458FEA3); + FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+12), 0xF4933D7E); + FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+15), 0x0D95748F); + FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+13), 0x728EB658); + FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0x718BCD58); + FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0x82154AEE); + FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x7B54A41D); + FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0xC25A59B5); + + /* Pass 3 */ + FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x9C30D539); + FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x2AF26013); + FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 4), 0xC5D1B023); + FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0x286085F0); + FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28), 0xCA417918); + FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+17), 0xB8DB38EF); + FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 8), 0x8E79DCB0); + FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+22), 0x603A180E); + + FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+29), 0x6C9E0E8B); + FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0xB01E8A3E); + FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+25), 0xD71577C1); + FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+12), 0xBD314B27); + FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+24), 0x78AF2FDA); + FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+30), 0x55605C60); + FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0xE65525F3); + FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+26), 0xAA55AB94); + + FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+31), 0x57489862); + FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+15), 0x63E81440); + FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 7), 0x55CA396A); + FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3), 0x2AAB10B6); + FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0xB4CC5C34); + FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w ), 0x1141E8CE); + FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+18), 0xA15486AF); + FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0x7C72E993); + + FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+13), 0xB3EE1411); + FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x636FBC2A); + FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x2BA9C55D); + FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+10), 0x741831F6); + FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+23), 0xCE5C3E16); + FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x9B87931E); + FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 5), 0xAFD6BA33); + FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 2), 0x6C24CF5C); + +#if PASS >= 4 + /* Pass 4. executed only when PASS =4 or 5 */ + FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24), 0x7A325381); + FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 4), 0x28958677); + FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w ), 0x3B8F4898); + FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+14), 0x6B4BB9AF); + FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0xC4BFE81B); + FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 7), 0x66282193); + FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x61D809CC); + FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23), 0xFB21A991); + + FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+26), 0x487CAC60); + FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x5DEC8032); + FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+30), 0xEF845D5D); + FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0xE98575B1); + FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDC262302); + FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0xEB651B88); + FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+19), 0x23893E81); + FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 3), 0xD396ACC5); + + FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+22), 0x0F6D6FF3); + FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+11), 0x83F44239); + FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+31), 0x2E0B4482); + FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+21), 0xA4842004); + FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 8), 0x69C8F04A); + FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+27), 0x9E1F9B5E); + FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+12), 0x21C66842); + FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 9), 0xF6E96C9A); + + FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 1), 0x670C9C61); + FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+29), 0xABD388F0); + FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 5), 0x6A51A0D2); + FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+15), 0xD8542F68); + FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x960FA728); + FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xAB5133A3); + FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0x6EEF0B6C); + FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+13), 0x137A3BE4); +#endif + +#if PASS == 5 + /* Pass 5. executed only when PASS = 5 */ + FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+27), 0xBA3BF050); + FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0x7EFB2A98); + FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0xA1F1651D); + FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+26), 0x39AF0176); + FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x66CA593E); + FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x82430E88); + FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+20), 0x8CEE8619); + FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+29), 0x456F9FB4); + + FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x7D84A5C3); + FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w ), 0x3B8B5EBE); + FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+12), 0xE06F75D8); + FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 7), 0x85C12073); + FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+13), 0x401A449F); + FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 8), 0x56C16AA6); + FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x4ED3AA62); + FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+10), 0x363F7706); + + FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x1BFEDF72); + FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x429B023D); + FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+14), 0x37D0D724); + FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+30), 0xD00A1248); + FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDB0FEAD3); + FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 6), 0x49F1C09B); + FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x075372C9); + FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+24), 0x80991B7B); + + FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 2), 0x25D479D8); + FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0xF6E8DEF7); + FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+16), 0xE3FE501A); + FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0xB6794C3B); + FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4), 0x976CE0BD); + FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 1), 0x04C006BA); + FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+25), 0xC1A94FB6); + FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15), 0x409F60C4); +#endif + + state->fingerprint[0] += t0; + state->fingerprint[1] += t1; + state->fingerprint[2] += t2; + state->fingerprint[3] += t3; + state->fingerprint[4] += t4; + state->fingerprint[5] += t5; + state->fingerprint[6] += t6; + state->fingerprint[7] += t7; +} + +/* tailor the last output */ +static void haval_tailor (haval_state* state) +{ + haval_word temp; + +#if FPTLEN == 128 + temp = (state->fingerprint[7] & 0x000000FF) | + (state->fingerprint[6] & 0xFF000000) | + (state->fingerprint[5] & 0x00FF0000) | + (state->fingerprint[4] & 0x0000FF00); + state->fingerprint[0] += rotate_right(temp, 8); + + temp = (state->fingerprint[7] & 0x0000FF00) | + (state->fingerprint[6] & 0x000000FF) | + (state->fingerprint[5] & 0xFF000000) | + (state->fingerprint[4] & 0x00FF0000); + state->fingerprint[1] += rotate_right(temp, 16); + + temp = (state->fingerprint[7] & 0x00FF0000) | + (state->fingerprint[6] & 0x0000FF00) | + (state->fingerprint[5] & 0x000000FF) | + (state->fingerprint[4] & 0xFF000000); + state->fingerprint[2] += rotate_right(temp, 24); + + temp = (state->fingerprint[7] & 0xFF000000) | + (state->fingerprint[6] & 0x00FF0000) | + (state->fingerprint[5] & 0x0000FF00) | + (state->fingerprint[4] & 0x000000FF); + state->fingerprint[3] += temp; + +#endif +#if FPTLEN == 160 + temp = (state->fingerprint[7] & (haval_word)0x3F) | + (state->fingerprint[6] & ((haval_word)0x7F << 25)) | + (state->fingerprint[5] & ((haval_word)0x3F << 19)); + state->fingerprint[0] += rotate_right(temp, 19); + + temp = (state->fingerprint[7] & ((haval_word)0x3F << 6)) | + (state->fingerprint[6] & (haval_word)0x3F) | + (state->fingerprint[5] & ((haval_word)0x7F << 25)); + state->fingerprint[1] += rotate_right(temp, 25); + + temp = (state->fingerprint[7] & ((haval_word)0x7F << 12)) | + (state->fingerprint[6] & ((haval_word)0x3F << 6)) | + (state->fingerprint[5] & (haval_word)0x3F); + state->fingerprint[2] += temp; + + temp = (state->fingerprint[7] & ((haval_word)0x3F << 19)) | + (state->fingerprint[6] & ((haval_word)0x7F << 12)) | + (state->fingerprint[5] & ((haval_word)0x3F << 6)); + state->fingerprint[3] += temp >> 6; + + temp = (state->fingerprint[7] & ((haval_word)0x7F << 25)) | + (state->fingerprint[6] & ((haval_word)0x3F << 19)) | + (state->fingerprint[5] & ((haval_word)0x7F << 12)); + state->fingerprint[4] += temp >> 12; + +#endif +#if FPTLEN == 192 + temp = (state->fingerprint[7] & (haval_word)0x1F) | + (state->fingerprint[6] & ((haval_word)0x3F << 26)); + state->fingerprint[0] += rotate_right(temp, 26); + + temp = (state->fingerprint[7] & ((haval_word)0x1F << 5)) | + (state->fingerprint[6] & (haval_word)0x1F); + state->fingerprint[1] += temp; + + temp = (state->fingerprint[7] & ((haval_word)0x3F << 10)) | + (state->fingerprint[6] & ((haval_word)0x1F << 5)); + state->fingerprint[2] += temp >> 5; + + temp = (state->fingerprint[7] & ((haval_word)0x1F << 16)) | + (state->fingerprint[6] & ((haval_word)0x3F << 10)); + state->fingerprint[3] += temp >> 10; + + temp = (state->fingerprint[7] & ((haval_word)0x1F << 21)) | + (state->fingerprint[6] & ((haval_word)0x1F << 16)); + state->fingerprint[4] += temp >> 16; + + temp = (state->fingerprint[7] & ((haval_word)0x3F << 26)) | + (state->fingerprint[6] & ((haval_word)0x1F << 21)); + state->fingerprint[5] += temp >> 21; + +#endif +#if FPTLEN == 224 + state->fingerprint[0] += (state->fingerprint[7] >> 27) & 0x1F; + state->fingerprint[1] += (state->fingerprint[7] >> 22) & 0x1F; + state->fingerprint[2] += (state->fingerprint[7] >> 18) & 0x0F; + state->fingerprint[3] += (state->fingerprint[7] >> 13) & 0x1F; + state->fingerprint[4] += (state->fingerprint[7] >> 9) & 0x0F; + state->fingerprint[5] += (state->fingerprint[7] >> 4) & 0x1F; + state->fingerprint[6] += state->fingerprint[7] & 0x0F; +#endif +} + diff --git a/src/core/haval.h b/src/core/haval.h new file mode 100644 index 0000000..e9489dd --- /dev/null +++ b/src/core/haval.h @@ -0,0 +1,130 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* + * haval.h: specifies the interface to the HAVAL (V.1) hashing library. + * + * HAVAL is a one-way hashing algorithm with the following + * collision-resistant property: + * It is computationally infeasible to find two or more + * messages that are hashed into the same fingerprint. + * + * Reference: + * Y. Zheng, J. Pieprzyk and J. Seberry: + * ``HAVAL --- a one-way hashing algorithm with variable + * length of output'', Advances in Cryptology --- AUSCRYPT'92, + * Lecture Notes in Computer Science, Springer-Verlag, 1993. + * + * This library provides routines to hash + * - a string, + * - a file, + * - input from the standard input device, + * - a 32-word block, and + * - a string of specified length. + * + * Author: Yuliang Zheng + * Department of Computer Science + * University of Wollongong + * Wollongong, NSW 2522, Australia + * Email: yuliang@cs.uow.edu.au + * Voice: +61 42 21 4331 (office) + * + * Date: June 1993 + * + * Copyright (C) 1993 by C^3SR. All rights reserved. + * This program may not be sold or used as inducement to + * buy a product without the written permission of C^3SR. + * + * Descriptions: + * + * Note: + * 1. In general, HAVAL is faster on a little endian + * machine than on a big endian one. + * + * 2. The test program "havaltest.c" provides an option + * for testing the endianity of your machine. + * + * 3. The speed of HAVAL is even more remarkable on a + * machine that has a large number of internal registers. + * + * PASS define the number of passes (3, 4, or 5) + * FPTLEN define the length of a fingerprint (128, 160, 192, 224 or 256) + */ + +#ifndef __HAVAL_H +#define __HAVAL_H + +#ifndef PASS +#define PASS 3 /* 3, 4, or 5 */ +#endif + +#ifndef FPTLEN +#define FPTLEN 128 /* 128, 160, 192, 224 or 256 */ +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +typedef uint32 haval_word; /* a HAVAL word = 32 bits */ + +typedef struct { + haval_word count[2]; /* number of bits in a message */ + haval_word fingerprint[8]; /* current state of fingerprint */ + haval_word block[32]; /* buffer for a 32-word block */ + uint8 remainder[32*4]; /* unhashed chars (No.<128) */ +} haval_state; + +/* Do not remove this line. Protyping depends on it! +#if defined(__STDC__) || defined(__cplusplus) +#define P_(s) s +#else +#define P_(s) () +#endif +*/ + +#define P_(s) s +//Old prototyping stuff... I will ignore it for now. + +void haval_string P_((char *, uint8 *)); /* hash a string */ +int haval_file P_((char *, uint8 *)); /* hash a file */ +void haval_stdin P_((void)); /* filter -- hash input from stdin */ +void haval_start P_((haval_state *)); /* initialization */ +void haval_hash P_((haval_state* state, uint8* str, int str_len)); +void haval_end P_((haval_state *, uint8 *)); /* finalization */ +void haval_hash_block P_((haval_state *)); /* hash a 32-word block */ + +#endif //__HAVAL_H + diff --git a/src/core/md5.cpp b/src/core/md5.cpp new file mode 100644 index 0000000..1a265b7 --- /dev/null +++ b/src/core/md5.cpp @@ -0,0 +1,302 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/*********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ** Revised (for MD5): RLR 4/27/91 ** + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + **********************************************************************/ +#include "stdcore.h" +#include "md5.h" + +/* forward declaration */ +static void Transform (uint32*, uint32*); + +static uint8 PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#ifdef UNICOS +# define ROTATE_LEFT(x,n) (((x) << (n)) | (((x) & 0xffffffff) >> (32-(n)))) +#else +# define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#endif + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* The routine MD5Init initializes the message-digest context + mdContext. All fields are set to zero. */ +void MD5Init (MD5_CTX* mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (uint32)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (uint32)0x67452301; + mdContext->buf[1] = (uint32)0xefcdab89; + mdContext->buf[2] = (uint32)0x98badcfe; + mdContext->buf[3] = (uint32)0x10325476; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. */ +void MD5Update (MD5_CTX* mdContext, uint8* inBuf, unsigned int inLen) +{ + uint32 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ +#ifndef UNICOS + if ((mdContext->i[0] + ((uint32)inLen << 3)) < mdContext->i[0]) +#else + if (((mdContext->i[0]+((uint32)inLen << 3)) & 0xffffffff) < mdContext->i[0]) +#endif + + mdContext->i[1]++; + + mdContext->i[0] += ((uint32)inLen << 3); + mdContext->i[1] += ((uint32)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((uint32)mdContext->in[ii+3]) << 24) | + (((uint32)mdContext->in[ii+2]) << 16) | + (((uint32)mdContext->in[ii+1]) << 8) | + ((uint32)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. */ +void MD5Final (MD5_CTX* mdContext) +{ + uint32 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((uint32)mdContext->in[ii+3]) << 24) | + (((uint32)mdContext->in[ii+2]) << 16) | + (((uint32)mdContext->in[ii+1]) << 8) | + ((uint32)mdContext->in[ii]); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (uint8)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (uint8)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (uint8)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (uint8)((mdContext->buf[i] >> 24) & 0xFF); + } +} + +/* Basic MD5 step. Transforms buf based on in. */ +static void Transform (uint32* buf, uint32* in) +{ + uint32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, 0xd76aa478); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, 0xe8c7b756); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, 0x242070db); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, 0xc1bdceee); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, 0xf57c0faf); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, 0x4787c62a); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, 0xa8304613); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, 0xfd469501); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, 0x698098d8); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, 0x8b44f7af); /* 10 */ + FF ( c, d, a, b, in[10], S13, 0xffff5bb1); /* 11 */ + FF ( b, c, d, a, in[11], S14, 0x895cd7be); /* 12 */ + FF ( a, b, c, d, in[12], S11, 0x6b901122); /* 13 */ + FF ( d, a, b, c, in[13], S12, 0xfd987193); /* 14 */ + FF ( c, d, a, b, in[14], S13, 0xa679438e); /* 15 */ + FF ( b, c, d, a, in[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, 0xf61e2562); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, 0xc040b340); /* 18 */ + GG ( c, d, a, b, in[11], S23, 0x265e5a51); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, 0xd62f105d); /* 21 */ + GG ( d, a, b, c, in[10], S22, 0x2441453); /* 22 */ + GG ( c, d, a, b, in[15], S23, 0xd8a1e681); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, 0x21e1cde6); /* 25 */ + GG ( d, a, b, c, in[14], S22, 0xc33707d6); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, 0xf4d50d87); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, 0x455a14ed); /* 28 */ + GG ( a, b, c, d, in[13], S21, 0xa9e3e905); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, 0xfcefa3f8); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, 0x676f02d9); /* 31 */ + GG ( b, c, d, a, in[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, 0xfffa3942); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, 0x8771f681); /* 34 */ + HH ( c, d, a, b, in[11], S33, 0x6d9d6122); /* 35 */ + HH ( b, c, d, a, in[14], S34, 0xfde5380c); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, 0xa4beea44); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, 0x4bdecfa9); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, 0xf6bb4b60); /* 39 */ + HH ( b, c, d, a, in[10], S34, 0xbebfbc70); /* 40 */ + HH ( a, b, c, d, in[13], S31, 0x289b7ec6); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, 0xeaa127fa); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, 0xd4ef3085); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, 0x4881d05); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, 0xd9d4d039); /* 45 */ + HH ( d, a, b, c, in[12], S32, 0xe6db99e5); /* 46 */ + HH ( c, d, a, b, in[15], S33, 0x1fa27cf8); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, 0xf4292244); /* 49 */ + II ( d, a, b, c, in[ 7], S42, 0x432aff97); /* 50 */ + II ( c, d, a, b, in[14], S43, 0xab9423a7); /* 51 */ + II ( b, c, d, a, in[ 5], S44, 0xfc93a039); /* 52 */ + II ( a, b, c, d, in[12], S41, 0x655b59c3); /* 53 */ + II ( d, a, b, c, in[ 3], S42, 0x8f0ccc92); /* 54 */ + II ( c, d, a, b, in[10], S43, 0xffeff47d); /* 55 */ + II ( b, c, d, a, in[ 1], S44, 0x85845dd1); /* 56 */ + II ( a, b, c, d, in[ 8], S41, 0x6fa87e4f); /* 57 */ + II ( d, a, b, c, in[15], S42, 0xfe2ce6e0); /* 58 */ + II ( c, d, a, b, in[ 6], S43, 0xa3014314); /* 59 */ + II ( b, c, d, a, in[13], S44, 0x4e0811a1); /* 60 */ + II ( a, b, c, d, in[ 4], S41, 0xf7537e82); /* 61 */ + II ( d, a, b, c, in[11], S42, 0xbd3af235); /* 62 */ + II ( c, d, a, b, in[ 2], S43, 0x2ad7d2bb); /* 63 */ + II ( b, c, d, a, in[ 9], S44, 0xeb86d391); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + + diff --git a/src/core/md5.h b/src/core/md5.h new file mode 100644 index 0000000..d82b54b --- /dev/null +++ b/src/core/md5.h @@ -0,0 +1,62 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/*********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + **********************************************************************/ + +/* $Tripwire: md5.h,v 1.1 2000/10/28 01:15:20 itripn Exp $ */ + +#ifndef __MD5_H +#define __MD5_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + uint32 i[2]; /* number of _bits_ handled mod 2^64 */ + uint32 buf[4]; /* scratch buffer */ + uint8 in[64]; /* input buffer */ + uint8 digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init(MD5_CTX*); +void MD5Update(MD5_CTX*, uint8*, unsigned int); +void MD5Final(MD5_CTX*); + +#endif //__MD5_H + diff --git a/src/core/msystem.cpp b/src/core/msystem.cpp new file mode 100644 index 0000000..f2325fa --- /dev/null +++ b/src/core/msystem.cpp @@ -0,0 +1,1027 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* LINTLIBRARY */ +/* + * This is the file with all the library routines in it + * + * Author information: + * Matt Bishop + * Department of Computer Science + * University of California at Davis + * Davis, CA 95616-8562 + * phone (916) 752-8060 + * email bishop@cs.ucdavis.edu + * + * This code is placed in the public domain. I do ask that + * you keep my name associated with it, that you not represent + * it as written by you, and that you preserve these comments. + * This software is provided "as is" and without any guarantees + * of any sort. + * + * Version information: + * 1.0 May 25, 1994 Matt Bishop + * 1.1 July 5, 1994 Matt Bishop + * added TZ to the list of environment variables to be + * passed on by default; you get what the environment + * gives you (as required by System V based systems) + * 1.2 October 4, 1994 Matt Bishop + * added mxfpopen, mxfpclose; also cleaned up le_set(), + * in that before if you added a predefined environment + * variable as the first variable, it would process it, + * initialize the environment list (first call), and + * then append the name; now if le_set() is called, it + * initializes the environment and then does the checking + * 1.3 October 31, 1994 Matt Bishop + * made the globals static for better modularity + */ + +#include "stdcore.h" + +#if IS_UNIX + +/* + * set, reset environment to be passed to mpopem + */ +#include +#include +#include +#include +#include +#include +#if defined(HAVE_MALLOC_H) +#include +#endif +#include +//#include +#include "tw_signal.h" +#ifdef __STDC__ +# include +# include +#endif +#include +#include +#include "msystem.h" + +/* + * signal type + */ +#ifndef SIG_TYPE +# define SIG_TYPE void +#endif + +/* + * define error message printer + */ +#define ERMSG(x) if (le_verbose){ \ + (void) fprintf(stderr, "SE internal error: ");\ + (void) fprintf(stderr, "%s(%d): %s\n", \ + __FILE__, __LINE__-4, x); \ + } + +/* + * define limits + * + * for the popen/pclose clones, we need to store PIDs in an array; + * how big should it be? answer: since each popen call requires 1 + * pipe, it can only be as big as the maximim number of pipes allowed + * that number is MAX_MPOPEN + */ +#ifndef MAX_MPOPEN +# define MAX_MPOPEN 20 +#endif +/* + * all environment variable arrays are dynamically allocated; if they are + * too small, they grow by PTR_INC to accommodate the new variable + * changing this just causes more (or less) allocations; it's an efficiency + * consideration, not a security or system one + */ +#define PTR_INC 1024 /* how much to increment pointer arrays */ +/* + * this is the maximum number of signals; we use NSIG if that's + * defined, otherwise 32 (which seems to be right for most systems) + */ +#ifdef NSIG +# define MAX_SIGNAL NSIG +#else +# define MAX_SIGNAL 32 +#endif +/* + * this is the maximum number of file descriptors (NFILES if + * defined, otherwise 256 (which seems to be right for most systems) + */ +#ifdef NFILES +# define MAX_DESC NFILES +#else +# define MAX_DESC 256 +#endif + +/* + * in case the subprocess fails to exec the command properly + */ +#define EXIT_BAD -1 /* oops! */ + +/* + * now, the environment + * + * the default environment; you get the bare bones here. + * to add to it, just stick the new environment variables + * at the end of the array; the program does the rest automatically + */ +char *nvfix[] = { /* these MUST be set or reset */ + DEF_PATH, /* a safe path */ + DEF_SHELL, /* a safe shell */ + DEF_IFS, /* a safe IFS */ + DEF_TZ, /* the current time zone */ + NULL /* add new ones here */ +}; +#define SZ_NVFIX (sizeof(nvfix)/sizeof(char *)) /* size of nvfix */ +static int octmask = DEF_UMASK; /* default umask */ +static int mresetgid = UID_RESET; /* reset EGID to RGID by default */ +static int mresetuid = GID_RESET; /* reset EUID to RUID by default */ +static int fdleave[MAX_DESC]; /* 1 to keep file descriptor open */ +static char **envp = NULL; /* environment passed to child */ +static int sz_envp = 0; +static int nend = 0; /* # entries in envp */ +static int le_verbose = 1; /* 1 to print error messages */ + +/* + * structure for malloc + */ +union xyzzy { + char **cpp; /* doubly-indirect pointer */ +#ifdef __STDC__ + void *vp; /* generic pointer */ +#else + char *vp; /* generic pointer */ +#endif +}; /* used to cast malloc properly */ + +/* + * library functions + */ +#ifndef __STDC__ +char *getenv(); /* get variable from environment */ +#endif +/************* U T I L I T Y F U N C T I O N S *******************/ + +/* + * string duplication into private memory + * on some systems, this is a library function, so define STRDUP + * if it is on yours + */ +#ifdef STRDUP +# ifndef __STDC__ + char *strdup(); +# endif +#else +# ifdef __STDC__ + static char *strdup(char *str) +# else + static char *strdup(str) + char *str; +# endif + { + register char *p; /* temp pointer */ + + /* + * allocate space for the string, and copy if successful + */ + if ((p = (char*)malloc((unsigned)((strlen(str)+1)*sizeof(char)))) + != NULL) + (void) strcpy(p, str); + return(p); + } +#endif + + +/* + * allocate space for an array of pointers, OR + * (if space already allocated) increase the allocation by PTR_INC + */ +#ifdef __STDC__ +static char **c2alloc(char **old, int *sz_alloc) +#else +static char **c2alloc(old, sz_alloc) +char **old; +int *sz_alloc; +#endif +{ + register int i; /* counter in a for loop */ + union xyzzy x; /* used to cast malloc properly */ + + /* + * allocate space for the new (expanded) array + */ + x.vp = malloc((unsigned) ((*sz_alloc + PTR_INC) * sizeof(char *))); + if (x.vp != NULL){ + /* success! copy the old and free it, if appropriate */ + if (old != NULL){ + for(i = 0; i < *sz_alloc; i++) + x.cpp[i] = old[i]; + x.cpp = old; + (void) free(x.vp); + } + /* now have PTR_INC more room */ + *sz_alloc += PTR_INC; + } + + /* + * return pointer to new space + */ + return(x.cpp); +} + +#ifdef __STDC__ +static int initenv(void) +#else +static int initenv() +#endif +{ + register int i; + register int rval; + + if (envp != NULL) + le_clobber(); + for(i = 0; nvfix[i] != NULL; i++) + if ((rval = le_set(nvfix[i])) != SE_NONE) + return(rval); + return(SE_NONE); +} + +/************* E N V I R O N M E N T C O N T R O L *******************/ + +/* + * clobber the internal environment + */ +#ifdef __STDC__ +void le_clobber(void) +#else +void le_clobber() +#endif +{ + register int i; /* counter in a for loop */ + union { + char **ep; + char *p; + } x; + + /* + * if the environment is defined and not fixed, clobber it + */ + if (envp != NULL){ + /* it's defined -- is it fixed? */ + if (envp != nvfix){ + /* no -- usual walk the list crud */ + for(i = 0; envp[i] != NULL; i++) + (void) free(envp[i]); + x.ep = envp; + (void) free(x.p); + } + /* say there's not anything there any more */ + envp = NULL; + } + + /* + * now clobber the sizes + */ + nend = sz_envp = 0; +} + +/* + * get a pointer to the environment element + */ +#ifdef __STDC__ +static int le_getenv(char *var) +#else +static int le_getenv(var) +char *var; +#endif +{ + register int i; /* counter in a for loop */ + register char *p, *q; /* used to compare two strings */ + + /* + * check for no environment + */ + if (envp == NULL) + return(-1); + + /* + * there is one -- now walk the environment list + */ + for(i = 0; envp[i] != NULL; i++){ + /* compare */ + p = envp[i]; + q = var; + while(*p && *q && *p == *q) + p++, q++; + /* have we a match? */ + if ((*p == '=' || *p == '\0') && (*q == '=' || *q == '\0')){ + /* YES -- return its index */ + return(i); + } + } + + /* + * no match + */ + return(-1); +} + +/* + * set an environment variable + */ +#ifdef __STDC__ +int le_set(char *env) +#else +int le_set(env) +char *env; +#endif +{ + register char *p, *q; /* what is to be put into env */ + register int n; /* where a previous definition is */ + + /* + * seeif youneed to create the environment list + */ + if (sz_envp == 0){ + if ((envp = c2alloc(envp, &sz_envp)) == NULL){ + ERMSG("ran out of memory"); + return(SE_NOMEM); + } + for(nend = 0; nvfix[nend] != NULL; nend++) + if ((envp[nend] = strdup(nvfix[nend])) == NULL){ + ERMSG("ran out of memory"); + return(SE_NOMEM); + } + envp[nend] = NULL; + } + + /* + * if there is an = sign, + * it's a redefinition; if not, + * just include it from the current environment + * (if not defined there, don't define it here) + */ + if (strchr(env, '=') == NULL){ + /* is it defined locally? */ + if ((q = getenv(env)) == NULL){ + /* no -- don't define it here */ + return(SE_NONE); + } + else if ((p = (char*)malloc((unsigned) (strlen(env)+strlen(q)+2))) + == NULL){ + ERMSG("ran out of memory"); + return(SE_NOMEM); + } + else{ + (void) strcpy(p, env); + (void) strcat(p, "="); + (void) strcat(p, q); + } + } + else if ((p = strdup(env)) == NULL){ + ERMSG("ran out of memory"); + return(SE_NOMEM); + } + + /* + * if it isn't defined, see if you need to create the environment list + */ + if (nend == sz_envp && (envp = c2alloc(envp, &sz_envp)) == NULL){ + ERMSG("ran out of memory"); + return(SE_NOMEM); + } + + /* + * add it to the environment + * if it is already defined, delete the old definition + * and replace it with the new definition + */ + if ((n = le_getenv(env)) > -1){ + (void) free(envp[n]); + envp[n] = p; + return(SE_NONE); + } + + envp[nend++] = p; + envp[nend] = NULL; + + /* + * all done + */ + return(SE_NONE); +} + +/* + * clear a current environment variable + */ +#ifdef __STDC__ +int le_unset(char *env) +#else +int le_unset(env) +char *env; +#endif +{ + register int i; /* counter in a for loop */ + + /* + * delete it from the environment + */ + if ((i = le_getenv(env)) > -1){ + (void) free(envp[i]); + for( ; envp[i] != NULL; i++) + envp[i] = envp[i+1]; + return(SE_NONE); + } + + /* + * no such variable + */ + return(SE_NOVAR); +} + +/* + * set the default umask + */ +#ifdef __STDC__ +int le_umask(int umak) +#else +int le_umask(umak) +int umak; +#endif +{ + /* + * reset the umask + */ + octmask = umak; + return(SE_NONE); +} + +/* + * leave a file descriptor open + */ +#ifdef __STDC__ +int le_openfd(int fd) +#else +int le_openfd(fd) +int fd; +#endif +{ + /* + * check args + */ + if (0 > fd || fd >= MAX_DESC) + return(SE_BADFD); + /* + * mark the descriptor for leaving open + */ + fdleave[fd] = 1; + return(SE_NONE); +} + +/* + * mark a file descriptor closed + */ +#ifdef __STDC__ +int le_closefd(int fd) +#else +int le_closefd(fd) +int fd; +#endif +{ + /* + * check args + */ + if (0 > fd || fd >= MAX_DESC) + return(SE_BADFD); + /* + * mark the descriptor for closing + */ + fdleave[fd] = 0; + return(SE_NONE); +} + +/************* P R I V I L E G E C O N T R O L *******************/ + +/* + * say how to handle the effective (and real) UIDs + */ +#ifdef __STDC__ +int le_euid(int uid) +#else +int le_euid( uid) +int uid; +#endif +{ + mresetuid = uid; + return(SE_NONE); +} + +/* + * say how to handle the effective (and real) GIDs + */ +#ifdef __STDC__ +int le_egid(int gid) +#else +int le_egid(gid) +int gid; +#endif +{ + mresetgid = gid; + return(SE_NONE); +} + +/************* S U B C O M M A N D E X E C U T I O N *******************/ + +/* + * get the shell to use for the subcommand + */ +#ifdef __STDC__ +static char *shellenv(void) +#else +static char *shellenv() +#endif +{ + register int i; /* counter in a for loop */ + register char *shptr; /* points to shell name */ + + /* + * error check; should never happen + */ + if (envp == NULL && (i = initenv()) != SE_NONE) + return(NULL); + + /* + * get the shell environment variable + */ + for(i = 0; envp[i] != NULL; i++) + if (strncmp(envp[i], "SHELL=", strlen("SHELL=")) == 0) + break; + /* + * not defined; use the default shell + */ + if (envp[i] == NULL) + shptr = NOSHELL; + else + shptr = strchr(envp[i], '=') + 1; + return(shptr); +} + +/* + * like system but A LOT safer + */ +#ifdef __STDC__ +int msystem(char *cmd) +#else +int msystem(cmd) +char *cmd; +#endif +{ + char *argv[5]; /* argument list */ + register char *p; /* temoporary pointers */ + register char *shptr; /* the program to be run */ + register int i; /* index number of child */ + + /* + * if it's NULL, initialize it + */ + if (envp == NULL && (i = initenv()) != SE_NONE) + return(i); + + /* + * get the SHELL variable (if any) + */ + shptr = shellenv(); + + /* + * set it up, just like popen + */ + argv[0] = ((p = strrchr(shptr, '/')) == NULL) ? shptr : p+1; + argv[1] = "-c"; + argv[2] = cmd; + argv[3] = NULL; + + /* + * run it + */ + if ((i = schild(shptr, argv, envp, (FILE **) NULL, octmask)) < 0) + return(127); + return(echild(i)); +} + +/* + * this structure holds the information associating + * file descriptors and PIDs. It ks needed as the mpopen/mpclose interface + * uses file pointers but the wait call needs a PID + */ +static struct popenfunc { /* association of pid, file pointer */ + int pid; /* the process identifier */ + FILE *fp; /* the file pointer */ +} pfunc[MAX_MPOPEN]; + +/* + * like popen but A LOT safer + */ +#ifdef __STDC__ +FILE *mpopen(char *cmd, char *mode) +#else +FILE *mpopen(cmd, mode) +char *cmd; +char *mode; +#endif +{ + char *argv[5]; /* argument list */ + register char *p; /* temoporary pointers */ + register char *shptr; /* the program to be run */ + FILE *fpa[3]; /* process communication descriptors */ + register int indx; /* index number of child */ + + /* + * see if anything is available + */ + for(indx = 0; indx < MAX_MPOPEN; indx++) + if (pfunc[indx].pid == 0) + break; + if (indx == MAX_MPOPEN) + return(NULL); + + /* + * now get the SHELL variable (if any) + */ + shptr = shellenv(); + + /* + * set it up, just like popen + */ + argv[0] = ((p = strrchr(shptr, '/')) == NULL) ? shptr : p+1; + argv[1] = "-c"; + argv[2] = cmd; + argv[3] = NULL; + + fpa[0] = (*mode == 'w') ? stdin : NULL; + fpa[1] = (*mode == 'r') ? stdout : NULL; + fpa[2] = NULL; + + /* + * run it + */ + if ((pfunc[indx].pid = schild(shptr, argv, envp, fpa, octmask)) < 0) + return(NULL); + return(pfunc[indx].fp = ((*mode == 'w') ? fpa[0] : fpa[1])); +} + +/* + * close the pipe + */ +#ifdef __STDC__ +int mpclose(FILE *fp) +#else +int mpclose(fp) +FILE *fp; +#endif +{ + register int indx; /* used to look for corresponding pid */ + register int rstatus; /* return status of command */ + + /* + * loop until you find the right process + */ + for(indx = 0; indx < MAX_MPOPEN; indx++) + if (pfunc[indx].fp == fp){ + /* got it ... flush and close the descriptor */ + (void) fflush(fp); + (void) fclose(fp); + /* get the status code fo the child */ + rstatus = echild(pfunc[indx].pid); + /* clear the entry and return the code */ + pfunc[indx].pid = 0; + return(rstatus); + } + + /* + * no such process - signal no child + */ + return(-1); +} + + +/* + * like popen but A LOT safer + * uses file descriptors for all three files + * (0, 1, 2) + */ +#ifdef __STDC__ +int mfpopen(char *cmd, FILE *fpa[]) +#else +int mfpopen(cmd, fpa) +char *cmd; +FILE *fpa[]; +#endif +{ + char *argv[5]; /* argument list */ + register char *p; /* temoporary pointers */ + register char *shptr; /* the program to be run */ + register int indx; /* index number of child */ + + /* + * see if anything is available + */ + for(indx = 0; indx < MAX_MPOPEN; indx++) + if (pfunc[indx].pid == 0) + break; + if (indx == MAX_MPOPEN) + return(-1); + + /* + * now get the SHELL variable (if any) + */ + shptr = shellenv(); + + /* + * set it up, just like popen + */ + argv[0] = ((p = strrchr(shptr, '/')) == NULL) ? shptr : p+1; + argv[1] = "-c"; + argv[2] = cmd; + argv[3] = NULL; + + /* + * run it + */ + if ((pfunc[indx].pid = schild(shptr, argv, envp, fpa, octmask)) < 0) + return(-1); + return(indx); +} + +/* + * close the pipe + */ +#ifdef __STDC__ +int mfpclose(int indx, FILE *fp[3]) +#else +int mfpclose(indx, fp) +int indx; +FILE *fp[]; +#endif +{ + register int rstatus; /* return status of command */ + + /* + * loop until you find the right process + */ + if (pfunc[indx].pid == 0) + return(-1); + /* got it ... flush and close the descriptor */ + if (fp[0] != NULL) + (void) fclose(fp[0]); + /* get the status code fo the child */ + rstatus = echild(pfunc[indx].pid); + /* clear the entry and return the code */ + pfunc[indx].pid = 0; + /* got it ... flush and close the descriptor */ + if (fp[1] != NULL) + (void) fclose(fp[1]); + if (fp[2] != NULL) + (void) fclose(fp[2]); + return(rstatus); +} + +/* + * like popen but A LOT safer + * uses arg vector, not command, and file descriptors 0, 1, 2 + */ +#ifdef __STDC__ +int mxfpopen(char *argv[], FILE *fpa[]) +#else +int mxfpopen(argv, fpa) +char *argv[]; +FILE *fpa[]; +#endif +{ + register int indx; /* index number of child */ + + /* + * see if anything is available + */ + for(indx = 0; indx < MAX_MPOPEN; indx++) + if (pfunc[indx].pid == 0) + break; + if (indx == MAX_MPOPEN) + return(-1); + + /* + * run it + */ + if ((pfunc[indx].pid = schild(argv[0], argv, envp, fpa, octmask)) < 0) + return(-1); + return(indx); +} + +/* + * close the pipe + */ +#ifdef __STDC__ +int mxfpclose(int indx, FILE *fp[3]) +#else +int mxfpclose(indx, fp) +int indx; +FILE *fp[]; +#endif +{ + return(mfpclose(indx, fp)); +} + +/* + * signal values + */ +static tw_sighandler_t savesig[MAX_SIGNAL]; + +/* + * spawn a child; the child's args and environment are as indicated, + * the file descriptors 0/1/2 are redirected to the open files fp[0]/ + * fp[1]/fp[2] if they are non-NULL, and the umask of the child is set + * to omask + */ +#ifdef __STDC__ +int schild(char *cmd, char **argp, char **envptr, FILE *fp[], int mask) +#else +int schild(cmd, argp, envptr, fp, mask) +char *cmd; +char **argp; +char **envptr; +FILE *fp[]; +int mask; +#endif +{ + int p[3][2]; /* pipes to/from child */ + register int i; /* counter in for loop */ + register int ch_pid; /* child PID */ + register int euid, egid; /* in case reset[gu]id is -1 */ + + /* + * create 1 pipe for each of standard input, output, error + */ + if (fp != NULL){ + if (pipe(p[0]) < 0 || pipe(p[1]) < 0 || pipe(p[2]) < 0){ + ERMSG("pipes couldn't be made"); + return(SE_NOPIPE); + } + } + + /* + * remember the effective uid + */ + euid = geteuid(); + egid = getegid(); + + /* + * spawn the child and make the pipes the subprocess stdin, stdout + */ + if ((ch_pid = fork()) == 0){ + /* now reset the uid and gid if desired */ + if (mresetgid < -1) (void) setgid(getgid()); + else if (mresetgid == -1) (void) setgid(egid); + else if (mresetgid > -1) (void) setgid(mresetgid); + if (mresetuid < -1) (void) setuid(getuid()); + else if (mresetuid == -1) (void) setuid(euid); + else if (mresetuid > -1) (void) setuid(mresetuid); + /* reset the umask */ + (void) umask(mask); + /* close the unused ends of the pipe */ + /* and all other files except 0, 1, 2 */ + for(i = 3; i < NOFILE; i++) + if (fp == NULL || (!fdleave[i] && i != p[0][0] + && i != p[1][1] && i != p[2][1])) + (void) close(i); + /* if the parent wants to read/write to the child, */ + /* dup the descriptor; we tell this if the input fp */ + /* array has a NULL in the slot (no interest) */ + if (fp != NULL){ + if (fp[0] != NULL){ + (void) dup2(p[0][0], 0); + } + (void) close(p[0][0]); + if (fp[1] != NULL){ + (void) dup2(p[1][1], 1); + } + (void) close(p[1][1]); + if (fp[2] != NULL){ + (void) dup2(p[2][1], 2); + } + (void) close(p[2][1]); + } + /* exec the command and environment */ + (void) execve(cmd, argp, envptr); + /* should never happen ... */ + _exit(EXIT_BAD); + } + /* + * parent process: if couldn't create child, error + */ + if (ch_pid != -1){ + /* + * ignore any signals until child dies + */ + for(i = 0; i < MAX_SIGNAL; i++) +#ifdef SIGCHLD + if (i != SIGCHLD) +#endif + savesig[i] = tw_sigign(i); + /* + * close unused end of pipes + */ + if (fp != NULL){ + (void) close(p[0][0]); + (void) close(p[1][1]); + (void) close(p[2][1]); + } + /* + * use a stdio interface for uniformity + */ + if (fp != NULL){ + if (fp[0] != NULL) + fp[0] = fdopen(p[0][1], "w"); + else + (void) close(p[0][1]); + if (fp[1] != NULL) + fp[1] = fdopen(p[1][0], "r"); + else + (void) close(p[1][0]); + if (fp[2] != NULL) + fp[2] = fdopen(p[2][0], "r"); + else + (void) close(p[2][0]); + } + } + + /* + * return child's PID + */ + return(ch_pid); +} + +/* + * wait for child to die + */ +#ifdef __STDC__ +int echild(int pid) +#else +int echild(pid) +int pid; +#endif +{ + + register int r; /* PID of process just exited */ + int status; /* status of wait call */ + + /* + * done; wait for child to terminate + */ + while((r = wait(&status)) != pid && r != -1) ; + /* + * if child already dead, assume an exit status of -1 + */ + if (r == -1) status = -1; + /* + * restore signal traps + */ + for(r = 0; r < MAX_SIGNAL; r++) + (void) tw_signal(r, savesig[r]); + /* + * return exit status + */ + return(status); +} + +#endif //#if IS_UNIX + diff --git a/src/core/msystem.h b/src/core/msystem.h new file mode 100644 index 0000000..bb9f943 --- /dev/null +++ b/src/core/msystem.h @@ -0,0 +1,131 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* + * This is the header file; include it in programs that use + * the more secure system call (or the more secure popen call) + * It also contains error codes and such + * + * Author information: + * Matt Bishop + * Department of Computer Science + * University of California at Davis + * Davis, CA 95616-8562 + * phone (916) 752-8060 + * email bishop@cs.ucdavis.edu + * + * This code is placed in the public domain. I do ask that + * you keep my name associated with it, that you not represent + * it as written by you, and that you preserve these comments. + * This software is provided "as is" and without any guarantees + * of any sort. + * + * Version information: + * 1.0 May 25, 1994 Matt Bishop + */ +/* + * forward declarations + */ +#ifdef __STDC__ +void le_clobber(void); +int le_set(char *); +int le_unset(char *); +int le_umask(int); +int le_openfd(int); +int le_closefd(int); +int le_euid(int); +int le_egid(int); +int msystem(char *); +FILE *mpopen(char *, char *); +int mpclose(FILE *); +int mfpopen(char *, FILE *[]); +int mfpclose(int, FILE *[]); +int mxfpopen(char *[], FILE *[]); +int mxfpclose(int, FILE *[]); +int schild(char *, char *[], char *[], FILE *[], int); +int echild(int); +#else +void le_clobber(); +int le_set(); +int le_unset(); +int le_umask(); +int le_openfd(); +int le_closefd(); +int le_euid(); +int le_egid(); +int msystem(); +FILE *mpopen(); +int mpclose(); +int mfpopen(); +int mfpclose(); +int mxfpopen(); +int mxfpclose(); +int schild(); +int echild(); +#endif + +/* + * define error codes + */ +#define SE_NONE 0 /* no error */ +#define SE_NOMEM -1 /* no memory */ +#define SE_NOPIPE -2 /* no pipes */ +#define SE_NOVAR -3 /* variable not defined */ +#define SE_BADFD -4 /* invalid file descriptor */ + +/* + * default security settings + */ +#ifndef DEF_UMASK +# define DEF_UMASK 077 /* only owner has privileges */ +#endif +#ifndef UID_RESET +# define UID_RESET -2 /* reset EUID to RUID */ +#endif +#ifndef GID_RESET +# define GID_RESET -2 /* reset EGID to RGID */ +#endif +#ifndef DEF_PATH +# define DEF_PATH "PATH=/bin:/usr/bin:/usr/ucb" /* default search path */ +#endif +#ifndef DEF_SHELL +# define DEF_SHELL "SHELL=/bin/sh" /* default shell */ +#endif +#ifndef DEF_IFS +# define DEF_IFS "IFS= \t\n" /* default IFS */ +#endif +#ifndef DEF_TZ +# define DEF_TZ "TZ" /* default TZ */ +#endif +#ifndef NOSHELL +# define NOSHELL "/bin/sh" /* use this if no shell */ +#endif + diff --git a/src/core/ntdbs.h b/src/core/ntdbs.h new file mode 100644 index 0000000..81ae8f2 --- /dev/null +++ b/src/core/ntdbs.h @@ -0,0 +1,234 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: ntdbs.h +* Date....: 09/16/99 +* Creator.: rdifalco +* +* Allows dbchar_t (aka: WCHAR16) to be used with basic_string. +* +* std::basic_string (aka: tss::dbstring) should be +* used instead of wc16_string! +* +* NOTE: If platform's wchar_t is already a dbchar_t (i.e. 2 bytes) +* then tss::dbstring and dbchar_t are synonyms for std::wstring +* and wchar_t. +*/ + +#ifndef __NTDBS_H +#define __NTDBS_H + +#include "stringutil.h" +#include "ntmbs.h" + +#if IS_KAI + #define IS_STDLIB_MODENA 1 // Has special char_traits req's! + #ifdef MSIPL_WCHART + #define MBSTATE_T_DEFINED + #endif +#else + #define IS_STDLIB_MODENA 0 + #define MBSTATE_T_DEFINED +#endif + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Char traits for WCHAR16 (aka dbchar_t) and NTMBCS (mctype_t) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#if ( WCHAR_IS_16_BITS ) + namespace tss { typedef std::wstring dbstring; } + +#elif ( WCHAR_IS_32_BITS ) + namespace std { template <> struct char_traits< dbchar_t >; } + namespace tss { typedef std::basic_string dbstring; } + +#else + #error "wchar_t is not correctly factored!" + +#endif + + +#if WCHAR_IS_32_BITS // We already have a dbstring implicitly in wstring!!! + +#include + +// specialize *std*::char_traits!!! + +template<> +struct std::char_traits< dbchar_t > +{ + typedef dbchar_t char_type; + typedef wint_t int_type; + typedef streampos pos_type; + typedef streamoff off_type; + +#ifdef MBSTATE_T_DEFINED + typedef mbstate_t state_type; +#else + typedef int state_type; // Shame on you KAI! This is ANSI-C! +#endif + + static + void assign( char_type& lhs, const char_type& rhs ) { + lhs = rhs; + } + + static + bool eq( const char_type& lhs, const char_type& rhs ) { + return lhs == rhs; + } + + static + bool lt( const char_type& lhs, const char_type& rhs ) { + return lhs < rhs; + } + + static + int compare( const char_type* lhs, const char_type* rhs, size_t N ) + { + for ( ; N; ++lhs, ++rhs, --N ) + if ( *lhs != *rhs ) + return ( *lhs < *rhs ) ? -1 : +1; + + return 0; + } + + static + size_t length( const char_type* psz ) + { + if ( psz == 0 ) + return 0; + else + { + const char_type* end; + for ( end = psz; *end; end++ ); + return (size_t)( end - psz ); + } + } + + static + char_type* copy( char_type* lhs, const char_type* rhs, size_t N ) + { + for ( char_type* at = lhs; N; ++at, ++rhs, --N ) + *at = *rhs; + + return lhs; + } + + static + const char_type* + find( const char_type* psz, size_t N, const char_type& ch ) + { + for ( ; N; ++psz, --N ) + if ( *psz == ch ) + return psz; + + return 0; + } + + static + char_type* move( char_type* lhs, const char_type* rhs, size_t N ) { + return (char_type*)memmove( lhs, rhs, N * sizeof(char_type) ); + } + + static + char_type* assign( char_type* lhs, size_t N, char_type ch ) + { + for ( char_type* at = lhs; N; ++at, --N ) + *at = ch; + return lhs; + } + + static + int_type not_eof( const int_type& ch ) { + return int_type( !eq( ch, eof() ) ? ch : ~ch ); + } + + static + char_type to_char_type( const int_type& ch ) + { + return + eq_int_type( ch, to_int_type( ch ) ) + ? ch + : char_type(0); + } + + static + int_type to_int_type( const char_type& ch ) { + return (int_type)ch; + } + + static + bool eq_int_type( const int_type& lhs, const int_type& rhs ) { + return lhs == rhs; + } + +#if IS_STDLIB_MODENA + + // CAUTION:RAD -- Extra members required by Modena!! + +#ifdef MBSTATE_T_DEFINED // This is ANSI-C *not* ANSI-C++!! + static + state_type get_state( pos_type pos ) { + return pos.state(); + } + + static + pos_type get_pos( pos_type pos, state_type state ) { + return pos_type( pos.offset(), state ); + } +#endif//MBSTATE_T_DEFINED + + static + char_type newline() { + return L'\n'; + } + + static + char_type eos() { + return 0; + } + +#endif//IS_STDLIB_MODENA + + static + int_type eof() { + return (wint_t)(0xFFFF); + } +}; + +#endif//WCHAR_IS_16_BITS // We already have a dbstring implicitly in wstring!!! + + +#endif//__NTDBS_H + diff --git a/src/core/ntmbs.cpp b/src/core/ntmbs.cpp new file mode 100644 index 0000000..97202cf --- /dev/null +++ b/src/core/ntmbs.cpp @@ -0,0 +1,248 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// + +/* +* Name....: ntmbs.cpp +* Date....: 08/31/99 +* Creator.: rdifalco +* +* Routines to make NTMBS processing easier. +*/ + +#include "stdcore.h" // for: pch +#include "ntmbs.h" // for: These Declarations + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Module-wide Helpers +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifndef TSS_Raise // Should add file and line info in _DEBUG mode!!!! + #define TSS_Raise( Xcpt, pkg, ids ) \ + throw Xcpt( TSS_GetString( pkg, ids ) ) + +#endif//TSS_Raise + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// NTMBS Utils -- Definition +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +/* +* TSS::mbsdec +* +* ntmbs_t mbsdec( const_ntmbs_t beg, const_ntmbs_t psz ); +* +* REQUIRES: +* const_ntmbs_t beg = pointer to beginning of ntmbs +* const_ntmbs_t psz = current mbchar_t pointer (legal MBCS boundary) +* +* EFFECTS: +* Move the supplied string pointer backwards by one character. +* NTMBS characters are handled correctly. +* +* POSTCONDITIONS: +* Returns non-const pointer after moving it. +* Returns NULL if beg >= psz. +*/ +ntmbs_t +tss::mbsdec( const_ntmbs_t beg, const_ntmbs_t curr ) +{ + cDebug dbg( "tss::mbsdec - " ); + dbg.TraceDebug( + "It is strongly reccommended you do not " + "iterate an NTMBS backwards!\n" ); + + if ( curr <= beg ) + { + TSS_Raise( + eCharacterEncoding, + cCore, + core::STR_ERR_UNDERFLOW ); + } + + // Keep going back while invalid, find first valid. + const_ntmbs_t prev = curr - 1; + for ( ; prev > beg && ::mblen( (char*)prev, curr - prev ) == -1; --prev ); + + if ( curr - prev > MB_CUR_MAX ) + { + prev = (curr - 1); + + dbg.TraceDebug( "Character Fault:%c\n", *prev ); + + if ( (unsigned char)*prev > 0x7F ) + dbg.TraceDebug( "Normalizing.\n" ); + + else + { + dbg.TraceDebug( "Incorrectly Formed, Cannot Normalize!\n" ); + TSS_Raise( + eCharacterEncoding, + cCore, + core::STR_ERR_BADCHAR ); + } + } + + return (ntmbs_t)prev; +} + + +/* +* TSS::mbsinc +* +* ntmbs_t mbsinc( const_ntmbs_t psz ); +* +* REQUIRES: +* const_ntmbs_t psz = current mbchar_t pointer (legal MBCS boundary) +* +* EFFECTS: +* Move the supplied string pointer forward by one character. +* NTMBS characters are handled correctly. +* +* POSTCONDITIONS: +* Returns non-const pointer after moving it. +*/ +ntmbs_t +tss::mbsinc( const_ntmbs_t psz ) +{ + cDebug dbg( "tss::mbsinc -" ); + + if ( psz == 0 ) + throw eCharacter( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + int nBytes = ::mblen( (char*)psz, MB_CUR_MAX ); + if ( nBytes == -1 ) + { + dbg.TraceDebug( "Character Fault: %c\n", *psz ); + if ( (unsigned char)*psz > 0x7F ) + { + dbg.TraceDebug( "Normalizing.\n" ); + return (((ntmbs_t)psz) + 1 ); + } + + dbg.TraceDebug( "Incorrectly Formed, Cannot Normalize!\n" ); + TSS_Raise( + eCharacterEncoding, + cCore, + core::STR_ERR_BADCHAR ); + } + + return ( ((ntmbs_t)psz) + nBytes ); +} + + +/* +* TSS::mbsbytes +* +* size_t mbsbytes( const_ntmbs_t psz, size_t nCount ); +* +* REQUIRES: +* const_ntmbs_t psz = current mbchar_t pointer (legal MBCS boundary) +* size_t nCount = the number of character to calculate bytes for +* +* EFFECTS: +* Calculates the number of bytes in a character range: +* +* while ( psz += mblen( psz ) <= nCount ); +* +* POSTCONDITIONS: +* Returns size_t value indicating bytes in the range of [0,nCount). +*/ +size_t +tss::mbsbytes( const_ntmbs_t psz, size_t nCount ) +{ + const_ntmbs_t at = psz; + while ( nCount-- ) + at = tss::mbsinc( at ); + + return (size_t)((char*)at - (char*)psz); +} + +/// To Null terminator + +size_t +tss::mbsbytes( const_ntmbs_t psz ) +{ + if ( psz == 0 ) + throw eCharacter( TSS_GetString( cCore, core::STR_ERR_ISNULL ) ); + + + const_ntmbs_t at; + for ( at = psz; *at; ++at ); + return (size_t)((char*)at - (char*)psz); +} + + + + +/* +* TSS::mbscount +* +* size_t mbscount( const_ntmbs_t psz, size_t nBytes ); +* +* REQUIRES: +* const_ntmbs_t psz = current mbchar_t pointer (legal MBCS boundary) +* size_t nBytes = the end of a byte range begining at psz + 0. +* +* EFFECTS: +* Calculate the number of legal MB characters in the specified byte range. +* +* while ( psz += mblen( psz ) <= nCount ); +* +* POSTCONDITIONS: +* Returns size_t value indicating characters in the range of [psz + 0, psz + nBytes). +*/ +size_t +tss_mbscount( const_ntmbs_t psz, size_t nBytes ) +{ + size_t nCount = 0; + const_ntmbs_t at = psz; + const_ntmbs_t end = psz + nBytes; + for ( ; at < end; nCount++, at = tss::mbsinc( at ) ); + return nCount; +} + +/// To Null terminator + +size_t +tss::mbscount( const_ntmbs_t psz ) +{ + size_t nCount = 0; + for ( ; *psz; psz = tss::mbsinc( psz ), nCount++ ); + return nCount; +} + +// eof: ntmbs.cpp + diff --git a/src/core/ntmbs.h b/src/core/ntmbs.h new file mode 100644 index 0000000..d3cc036 --- /dev/null +++ b/src/core/ntmbs.h @@ -0,0 +1,511 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: ntmbs.h +* Date....: 08/31/1999 +* Creator.: rdifalco +* +* Routines to handle NTMBS (null-terminated multi-byte character sequences) +* as well as mappings to work between NTMBS and like-sized character-type +* sequences. +*/ + +#ifndef __NTMBS_H +#define __NTMBS_H + + +/// Requirements. + +#include "error.h" // for: TSS_EXCEPTION +#include "package.h" // for: TSS_GetString +#include "corestrings.h" // for: Utility Strings + + +/// Type Definitions for Multiple (?), Double (16), and Wide Characters (32) + +//--Null-terminated Multibyte Character Sequence + +#ifndef NTMBS_T_DEFINED +#define NTMBS_T_DEFINED + #ifdef TSS_NTMBS_IS_UNSIGNED // Natural-sign by default + typedef unsigned char mbchar_t; + typedef unsigned char* ntmbs_t; + typedef const unsigned char* const_ntmbs_t; + #else //TSS_NTMBS_IS_UNSIGNED + typedef char mbchar_t; + typedef char* ntmbs_t; + typedef const char* const_ntmbs_t; + #endif//TSS_NTMBS_IS_UNSIGNED +#endif//NTMBS_T_DEFINED + + +//--Null-terminated Wide Character Sequence (Could be double or quad byte) + +#ifndef NTWCS_T_DEFINED +#define NTWCS_T_DEFINED + //typedef wchar_t wchar_t; + typedef wchar_t* ntwcs_t; + typedef const wchar_t* const_ntwcs_t; +#endif//NTWCS_T_DEFINED + + + +/// NOTE: Size Specific (2 [double] or 4 [quad] byte wide characters) + +//--Null-terminated double(2)-byte Character Sequence + +#ifndef NTDBS_T_DEFINED +#define NTDBS_T_DEFINED + #if WCHAR_IS_16_BITS + typedef wchar_t dbchar_t; // Same size but use NT's type + #else + typedef uint16 dbchar_t; + #endif + typedef dbchar_t* ntdbs_t; + typedef const dbchar_t* const_ntdbs_t; +#endif//NTDBS_T_DEFINED + + +//--Internal, "size-specific" types for type dispatched specializations + +#ifndef NTQBS_T_DEFINED +#define NTQBS_T_DEFINED + #if WCHAR_IS_32_BITS + typedef wchar_t qbchar_t; // Same size but use NT's type + #else + typedef uint32 qbchar_t; + #endif + typedef qbchar_t* ntqbs_t; + typedef const qbchar_t* const_ntqbs_t; +#endif//NTQBS_T_DEFINED + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// NTMBS Manipulators +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +TSS_EXCEPTION( eCharacter, eError ); +TSS_EXCEPTION( eCharacterEncoding, eCharacter ); + +namespace tss +{ + /// Specific Routines (Add as needed) + + ntmbs_t mbsdec( const_ntmbs_t, const_ntmbs_t ); + ntmbs_t mbsinc( const_ntmbs_t ); + + size_t mbsbytes( const_ntmbs_t, size_t ); + size_t mbscount( const_ntmbs_t, size_t ); + + size_t mbsbytes( const_ntmbs_t ); + size_t mbscount( const_ntmbs_t ); + + inline size_t mbslen( const_ntmbs_t psz ) { // RAD: Yeesh! + return tss::mbscount( psz ); + } +}//tss:: + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Character Sequence Independent Mappings +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// NOTE: In each, we first do the homogeneous charsize ver, then the hetero + +namespace tss +{ + /// Increment and Decrement Pointers by (N) + + //--DEC + + template< class CT > + inline + CT* strdec( const CT*, const CT* psz ) { + return const_cast( psz - 1 ); + } + +#if 0 + template<> + inline + ntmbs_t strdec( const_ntmbs_t beg, const_ntmbs_t cur ) { + return tss::mbsdec( beg, cur ); + } +#endif + + + //--INC + + template< class CT > + inline + CT* strinc( const CT* psz ) + { + ASSERT( psz ); + return const_cast( ( *psz ? psz + 1 : psz ) ); + } + + template< class CT, class SIZET > + inline + CT* strinc( const CT* psz, SIZET N ) + { + ASSERT( psz ); + return const_cast( ( *psz ? psz + N : psz ) ); + } + + + template<> + inline + ntmbs_t strinc( const_ntmbs_t psz ) + { + return tss::mbsinc( psz ); + } + + template<> + inline + ntmbs_t strinc( const_ntmbs_t psz, size_t N ) + { + ntmbs_t at = const_cast( psz ); + while ( N-- ) + at = tss::mbsinc( at ); + return at; + } + + + /// Byte and Character Count Mappings + + + //--BYTES + + template< class CT > + size_t strsize( const CT* psz ) + { + const CT* at = psz; + while ( *at ) at++; + return (size_t)((char*)at - (char*)psz); + } + + template< class CT > + size_t strsize( const CT*, size_t N ) + { + return N * sizeof(CT); + } + + template<> + inline size_t strsize( const_ntmbs_t psz ) { + return mbsbytes( psz ); + } + template<> + inline size_t strsize( const_ntmbs_t psz, size_t N ) { + return mbsbytes( psz, N ); + } + + + //--COUNT + + template< class CT > + size_t strcount( const CT* psz ) + { + const CT* at = psz; + while ( *at ) at++; + return (size_t)(at - psz); + } + + template< class CT > + size_t strcount( const CT*, size_t N ) + { + return N; + } + + template<> + inline size_t strcount( const_ntmbs_t psz ) { + return mbscount( psz ); + } + template<> + inline size_t strcount( const_ntmbs_t psz, size_t N ) { + return mbscount( psz, N ); + } + + +/* These are needed! However, it would be better to just create +a NTMBS aware string class (basic_string *can't* be) and be +done with it */ + +#ifdef TSS_NTMBS_AWARE_SEACH_COMPLETE + + /* CAUTION:RAD -- I changed the traversal logic from "!=" to + "<" to accomodate a basic_string whose end() member does not + correctly point after the last valid trail-byte in a string. + Really, at != end should be correct, but I don't want to leave + any room for error. At some point, these routines should be put + under unit test and have all occurances of "at < end" changed + to the "more on-purpose" "at != end". */ + + /// Various MULTIBYTE aware string searching routines.. + + //--FIND_FIRST: ITER + + template< class InputT, class E > + InputT + find_first( InputT beg, InputT end, const E& item ) + { + for ( ; beg < end && *beg != item; beg = (InputT)tss::strinc( beg ) ); + return beg; + } + + + //--FIND_LAST: ITER + + template< class InputT, class E > + InputT + find_last( InputT beg, InputT end, const E& item ) + { + InputT at = end; + for ( ; beg < end ; beg = (InputT)tss::strinc( beg ) ); + if ( *beg == item ) + at = beg; + + return at; + } + + + //--FIND_FIRST: STRING + + template< class StrT > + StrT::size_type + find_first( const StrT& sin, StrT::const_reference item ) + { + StrT::const_iterator + beg = sin.begin(); + end = sin.end(); + + StrT::size_type N; + for ( N = 0; beg < end; ++N, beg = (InputT)tss::strinc( beg ) ) + if ( *beg == item ) + return N; + + return StrT::npos; + } + + + //--FIND_LAST: STRING + + template< class StrT > + StrT::size_type + find_last( const StrT& sin, StrT::const_reference item ) + { + StrT::size_type N = 0; + StrT::size_type nResult = StrT::npos; + StrT::const_iterator + beg = sin.begin(); + end = sin.end(); + + for ( ; beg < end ; beg = (InputT)tss::strinc( beg ) ); + if ( *beg == item ) + nResult = N; + + return N; + } + + + //--FIND_FIRST_OF: ITER + + template< class InputT > + InputT + find_first_of( + InputT beg, + InputT end, + InputT setbeg, + InputT setend ) + { + InputT at; + for ( ; beg < end; beg = (InputT)tss::strinc( beg ) ); + for ( at = setbeg; setbeg < setend; at = (InputT)tss::strinc( at ) ) + if ( *beg == *at ) + return beg; + + return end; + } + + + //--FIND_FIRST_OF: STRING (SAFE!!!) + + template< class StrT > + StrT::size_type + find_first_of( const StrT& sin, StrT::const_iterator set ) + { + // Point to beg of input + StrT::iterator beg = sin.begin(); + + // Start Search + StrT::size_type N = 0; + for ( ; beg < sin.end(); ++N, beg = tss::strinc( beg ) ) + for ( StrT::const_iterator at = set; *at; at = tss::strinc( at ) ) + if ( *beg == *at ) + return N; + + return StrT::npos; + } + + + //--FIND_FIRST_OF: STRING (NOT SAFE!!!) + + template< class StrT > + StrT::size_type + find_first_of( + const StrT& sin, + StrT::const_iterator set, + StrT::size_type nPos, + StrT::size_type nCount ) + { + ASSERT( nPos < tss::strcount( sin.begin() ); + + if ( nCount > 0 && nPos < sin.size() ) + { + ASSERT( nCount > tss::strcount( set ) ); + StrT::const_iterator endset; // Get end of set + while ( nCount-- ) endset++; + + // Advance to nPos + StrT::const_iterator at = tss::strinc( sin.begin(), nPos ); + StrT::const_iterator end = sin.end(); + + // Start Search + StrT::size_type N = 0; + for ( ; at < end; ++N, at = tss::strinc( at ) ) + { + if ( tss::find( set, endset, *at ) != 0 ) + return N; + } + } + + return StrT::npos; + } + + + //--FIND_LAST_OF: ITER + + template< class InputT1, class InputT2 > + InputT + find_last_of( + const InputT1 beg, const InputT1 end, + const InputT2 setbeg, const InputT2 setend ) + { + const InputT1 ans = end; + for ( ; beg < end; beg = tss::strinc( beg ) ); + for ( InputT2 at = setbeg; setbeg != setend; at = tss::strinc( at ) ) + if ( *beg == *at ) + ans = beg; + + return ans; + } + + + //--FIND_LAST_OF: STRING (SAFE!!!) + + template< class StrT > + StrT::size_type + find_last_of( const StrT& sin, StrT::const_iterator set ) + { + StrT::size_type nResult = StrT::npos; + StrT::size_type N = 0; + for ( ; at < end; ++N, at = tss::strinc( at ) ) + { + for ( StrT::const_iterator at = set; *at; at = tss::strinc( at ) ) + if ( *beg == *at ) + nResult = N; + } + + return nResult; + } + + + template< class StrT > + StrT::size_type + find_last_of( + const StrT& sin, + StrT::const_iterator set, + StrT::size_type nStart, + StrT::size_type nCount ) + { + if ( nCount > 0 && sin.size() ) + { + for ( StrT::const_iterator at = sin.begin() + + (nStart < _Len ? nStart : _Len - 1); ; --_U) + if (_Tr::find(set, nCount, *_U) != 0) + return (_U - _Ptr); + else if (_U == _Ptr) + break; + } + + return StrT::npos; + } + + // TODO:RAD -- find_first_not_of; + // TODO:RAD -- find_last_not_of; + +#endif//TSS_NTMBS_AWARE_SEACH_COMPLETE + + namespace util + { + // Preserves bit values when enlarging a type to a size_t + // Good for preventing sign extension + template< class E > + inline + size_t + char_to_size( E ch ) + { + // if this fails, 'ch' can't be cast to a + // size_t and preserve bit values + // if this fails, then you must find another way + ASSERT( sizeof( size_t ) >= sizeof( E ) ); + + // assert that either 'ch' is an unsigned value (no sign extension possible) + // or that 'ch' is the same size as a size_t (no sign extension is possible as well) + // if this fails, then you must specialize this function like we did for 'char' + ASSERT( (int)(E)-1 > (int)0 || sizeof( size_t ) == sizeof( E ) ); + + return (size_t)ch; + } + + + inline + size_t + char_to_size( char ch ) + { + return (size_t)(unsigned char)ch; + } + } +}//tss:: + + +#endif//__NTMBS_H + diff --git a/src/core/objectpool.cpp b/src/core/objectpool.cpp new file mode 100644 index 0000000..bb9c51c --- /dev/null +++ b/src/core/objectpool.cpp @@ -0,0 +1,131 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// objectpool.cpp +#include "stdcore.h" +#include "objectpool.h" +#include "debug.h" + +//----------------------------------------------------------------------------- +// cBlockLink +//----------------------------------------------------------------------------- +class cBlockLink +{ +public: + cBlockLink(cBlockLink* pNext) : mpNext(pNext) {} + cBlockLink* Next() { return mpNext; } +private: + cBlockLink* mpNext; // pointer to the next link, or NULL +}; + + +//----------------------------------------------------------------------------- +// cBlockList +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cBlockList::cBlockList() : + mpBlocks(0) +{ +} + +cBlockList::~cBlockList() +{ + Clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Allocate +/////////////////////////////////////////////////////////////////////////////// +void* cBlockList::Allocate(int size) +{ + char* mem = new char[size + sizeof(cBlockLink)]; + mpBlocks = new(mem) cBlockLink(mpBlocks); + return mem + sizeof(cBlockLink); +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear +/////////////////////////////////////////////////////////////////////////////// +void cBlockList::Clear() +{ + while(mpBlocks) + { + cBlockLink* pLink = mpBlocks; + mpBlocks = mpBlocks->Next(); + pLink->~cBlockLink(); + delete [] (char*)(pLink); + } +} + +//----------------------------------------------------------------------------- +// cObjectPoolBase +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cObjectPoolBase::cObjectPoolBase(int objSize, int chunkSize) : + mObjectSize(objSize), + mChunkSize(chunkSize), + mpNextFree(0) +{ +} + +cObjectPoolBase::~cObjectPoolBase() +{ + //TODO -- assert that the number of instances left are 0. + Clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// AllocNewChunk +/////////////////////////////////////////////////////////////////////////////// +void cObjectPoolBase::AllocNewChunk() +{ + ASSERT(mpNextFree == 0); + + int size = mObjectSize * mChunkSize; + char* pBlock = (char*)mBlockList.Allocate(size); + + char* pLast = pBlock + size - mObjectSize; + for(char* pc = pBlock; pc < pLast; pc += mObjectSize) + { + ((cLink*)pc)->mpNext = (cLink*)(pc + mObjectSize); + } + ((cLink*)pLast)->mpNext = 0; + + mpNextFree = (cLink*)pBlock; +} + + diff --git a/src/core/objectpool.h b/src/core/objectpool.h new file mode 100644 index 0000000..1965823 --- /dev/null +++ b/src/core/objectpool.h @@ -0,0 +1,140 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// objectpool.h +// +// cBlockList -- a linked list of blocks of memory +// cObjectPoolBase -- a pool of equal-sized objects; constant time allocation +#ifndef __OBJECTPOOL_H +#define __OBJECTPOOL_H + +class cBlockLink; + +//----------------------------------------------------------------------------- +// cBlockList +//----------------------------------------------------------------------------- +class cBlockList +{ +public: + cBlockList(); + ~cBlockList(); + + void* Allocate(int size); + void Clear(); // releases everything in the block list +private: + cBlockLink* mpBlocks; // linked list of blocks +}; + +//----------------------------------------------------------------------------- +// cObjectPoolBase +//----------------------------------------------------------------------------- +class cObjectPoolBase +{ +public: + cObjectPoolBase(int objSize, int chunkSize); + ~cObjectPoolBase(); + // NOTE -- dtor is not virtual; therefore it is potentially dangerous to delete a pointer to + // this class unless you know for sure the dynamic class type has nothing to clean up. + + void* Alloc (); + void Free (void* pObj); + void Clear (); + //TODO -- add IsPointerValid() +private: + void AllocNewChunk(); // get another chunk to use... + + struct cLink + { + cLink* mpNext; + }; + + cBlockList mBlockList; + const int mObjectSize; // how big are the objects? + const int mChunkSize; // how big are the chunks we are allocating? + cLink* mpNextFree; // the next free object + //int mInstanceCount; // number of objects that are currently allocated but not freed. +}; + +//----------------------------------------------------------------------------- +// cObjectPool +// Note -- this template only works for classes that are constructed with their +// default ctor; I don't know how to extend this model to work for non-default +// ctors... +//----------------------------------------------------------------------------- +template +class cObjectPool : public cObjectPoolBase +{ +public: + cObjectPool(int chunkSize) : cObjectPoolBase(sizeof(T), chunkSize) {} + + T* New () { return new(cObjectPoolBase::Alloc()) T(); } + void Delete (T* pObj) { pObj->~T(); Free(pObj); } +}; + +//############################################################################# +// inline implementation +//############################################################################# +/////////////////////////////////////////////////////////////////////////////// +// Alloc +/////////////////////////////////////////////////////////////////////////////// +inline void* cObjectPoolBase::Alloc() +{ + if(! mpNextFree) + AllocNewChunk(); + + cLink* pRtn = mpNextFree; + mpNextFree = mpNextFree->mpNext; + return pRtn; +} + +/////////////////////////////////////////////////////////////////////////////// +// Free +/////////////////////////////////////////////////////////////////////////////// +inline void cObjectPoolBase::Free(void* pObj) +{ + cLink* pNew = (cLink*)pObj; + pNew->mpNext = mpNextFree; + mpNextFree = pNew; +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear +/////////////////////////////////////////////////////////////////////////////// +inline void cObjectPoolBase::Clear() +{ + mBlockList.Clear(); + mpNextFree = 0; +} + + +#endif //__OBJECTPOOL_H + diff --git a/src/core/objectpool_t.cpp b/src/core/objectpool_t.cpp new file mode 100644 index 0000000..fc90d0c --- /dev/null +++ b/src/core/objectpool_t.cpp @@ -0,0 +1,109 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// objectpool_t + +#include "stdcore.h" +#include "objectpool.h" +#include "debug.h" +#include "test/test.h" + + +// this is the struct we will use for testing purposes +struct cDog +{ + int i; + char c; + double d; + cDog() : i(53), c('f'), d(3.14) { cDebug d("cDog::cDog"); d.TraceDebug("Dog ctor...\n"); } + ~cDog() { cDebug d("cDog::~cDog"); d.TraceDebug("Dog dtor...\n"); } +}; + + +void TestObjectPool() +{ + int k, j; + cDebug d("TestObjectPool"); + + // first, just try the growing properties of the pool + cObjectPoolBase pool(10, 5); + d.TraceDebug("object size = 10, chunk size = 5\n"); + for(k=0; k < 12; k++) + { + d.TraceDebug("Allocating...\n"); + pool.Alloc(); + } + d.TraceDebug("Removing everything...\n"); + pool.Clear(); + + // test the template class + cObjectPool dogPool(3); + std::list lDog; + for(j=0; j < 7; j++) + { + lDog.push_back(dogPool.New()); + } + + std::list::iterator i; + for( i = lDog.begin(); i != lDog.end(); i++) + { + d.TraceDebug("dog contents: %d %c %lf\n", (*i)->i, (*i)->c, (*i)->d); + dogPool.Delete(*i); + } + lDog.clear(); + + // now, do some random insertions and deletions... + std::vector vAlloced; + for(k=0; k < 1000; k++) + { + if(rand() % 3 > 0 ) + { + // alloc + void* pNew = pool.Alloc(); + d.TraceDebug("Allocating %p\n", pNew); + vAlloced.push_back(pNew); + } + else + { + // free + int idx = rand() % vAlloced.size(); + std::vector::iterator vi = vAlloced.begin() + idx; + void* pGone = *vi; + d.TraceDebug("Removing %p\n", pGone); + pool.Free(pGone); + vAlloced.erase(vi); + } + } + + d.TraceDebug("Leaving...\n"); +} + diff --git a/src/core/package.cpp b/src/core/package.cpp new file mode 100644 index 0000000..f9ddae8 --- /dev/null +++ b/src/core/package.cpp @@ -0,0 +1,32 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// + diff --git a/src/core/package.h b/src/core/package.h new file mode 100644 index 0000000..5db4a06 --- /dev/null +++ b/src/core/package.h @@ -0,0 +1,211 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: package.h +// Date....: 05/08/99 +// Creator.: Robert DiFalco (rdifalco) +// +// These classes and macros make up the TSS package abstraction. +// +// In TSS, a package represent a single project file. This file +// can represent a LIB, DLL, EXE, or other source code "package". +// The package _classes_, work together to provide a single point +// of entry for all the resources a Package (such as a LIB of DLL +// module) wish to make available to itself and other packages. +// A typical example (in fact so typical that it is concretely +// modeled in the Package abstraction) are shared Message strings. +// Each package has a message table that can be accessed by other +// packages that cooperate in the same application. +// +// The major components of packaging are the package wrapper (or +// singleton) and the package representation. There may only be +// one copy of the package representation. Its members may be +// themselves singletons or shared. Using the package interface +// guarantees that all shared resources will be properely +// initialized before they are used. When creating a package +// representation you can declare other packages that your +// package depends on, ensuring that predicate packages and their +// resources will be initialized before the package that uses +// those resources. +// +// Contents of this File +// +// TSS_Package( cPackage ) +// TSS_BeginPackage( cPackage ) +// TSS_EndPackage( cPackage ) +// TSS_ImplementPackage( cPackage ) +// TSS_Dependency( cPackage ) +// +// TSS_DECLARE_STRINGTABLE +// TSS_GetString( cPackage, IDS ) +// +// TSS_BeginStringtable( cPackage ) +// TSS_StringEntry( IDS, "message" ) +// TSS_EndStringtable( cPackage ) +// +// TSS_BeginStringIds( package_namespace ) +// TSS_EndStringIds( package_namespace ) +// +// class cPackageBase_ +// class cPackage_ +// + +#ifndef __PACKAGE_H +#define __PACKAGE_H + +#include "resources.h" // for: cMessage_ + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Macro helpers +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +//--PACKAGE Helpers + +#define TSS_Package( pkg ) \ + pkg::GetInstance() // Access "the" Package obj + +#define TSS_Dependency( pkg ) \ + TSS_Package( pkg ) // Declare a Package Depend. + + + +#define TSS_BeginPackage( pkg ) \ + class pkg : public cPackageBase_< TCHAR > \ + { \ + public: \ + static pkg& GetInstance(); + + +#define TSS_EndPackage( pkg ) \ + }; + +#define TSS_ImplementPackage( pkg ) \ + pkg& pkg::GetInstance() \ + { \ + static bool bConstructed = false; \ + static pkg x; \ + if ( !bConstructed ) \ + { \ + bConstructed = true; \ + x.LoadStrings(); \ + } \ + return x; \ + } + + + + +//--STRINGTABLE Helperfs + +#define TSS_GetString( pkg, id ) \ + TSS_Package( pkg ).GetString( id ) // Access the Message String + + +#define TSS_DECLARE_STRINGTABLE \ + public: \ + Messages::String \ + GetString( \ + Messages::ConstKeyRef id ) const { \ + return m_messages.Get( id ); } \ + void LoadStrings(); \ + private: \ + Messages m_messages // Decare a Stringtable + + +#ifdef _DEBUG +#define TSS_BeginStringtable( pkg ) \ + void pkg::LoadStrings() \ + { cDebug d( #pkg "::LoadStrings()" ); \ + d.TraceDebug("Loading strings for " #pkg " package.\n"); \ + Messages::Pair astr[] = { // Define a Stringtable +#else // _DEBUG +#define TSS_BeginStringtable( pkg ) \ + void pkg::LoadStrings() \ + { Messages::Pair astr[] = { // Define a Stringtable +#endif // _DEBUG + +#define TSS_EndStringtable( pkg ) \ + }; m_messages.Put( \ + astr, astr + countof(astr) ); } // End define Strintable + + +#define TSS_StringEntry( id, s ) \ + Messages::Pair( id, s ) // Stringtable Entry + +#define TSS_BeginStringIds( pns ) \ + namespace pns { \ + enum { // Define String IDs + +#define TSS_EndStringIds( pns ) \ + }; } // End define String IDs + + + +//============================================================================= +// cPackageBase_ -- Base class for all Package Resources +//----------------------------------------------------------------------------- +// SYNOPSIS: +// This class is the base class for all package representations +// and, thus, establishes the package contract. It's interface +// is relied on by the Package singleton wrapper, TSS_Package. +// Since part of its contract is that there is only one package +// instance per package, none of its data members need be static +// allowing the client to assume that its constructor will only +// be called once. +// +// CONSTRAINTS: +// A Package representation template must be instantiated with a +// "character concept" that is a valid STDCPP NTCTS. +// This will most often be char (for NTBS), wchar_t (for NTWCS), +// but may also be unsigned char (for NTMBCS). +// +// INVARIANTS: +// m_nInstances <= 1 +// +// + +template< class CharT > +class cPackageBase_ +{ + public: + + typedef cMessages_< int, CharT > Messages; + + void LoadStrings() + { + } +}; + + +#endif//__PACKAGE_H + diff --git a/src/core/platform.h b/src/core/platform.h new file mode 100644 index 0000000..0b7d94c --- /dev/null +++ b/src/core/platform.h @@ -0,0 +1,224 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// platform.h +// + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef __PLATFORM_H +#define __PLATFORM_H + +//============================================================================= +// Enumerations +// +// For each of these "enumerations" we create unique integers identifying each +// variation. We group similar items together, such as OS_REDHAT and OS_SLACKWARE + +#define OS_UNKNOWN 0 +#define OS_WIN32 0x0101 +#define OS_AIX 0x0401 +#define OS_HPUX 0x0501 +#define OS_IRIX 0x0601 +#define OS_OSF1 0x0701 + +#define COMP_UNKNOWN 0 +#define COMP_MSVC 0x0101 +#define COMP_KAI_GCC 0x0201 +#define COMP_KAI_SUNPRO 0x0202 +#define COMP_KAI_GLIBC 0x0203 +#define COMP_KAI_VISUALAGE 0x0204 +#define COMP_KAI_HPANSIC 0x0205 +#define COMP_KAI_IRIX 0x0206 +#define COMP_KAI_OSF1ALPHA 0x0207 +#define COMP_SUNPRO 0x0301 + +//============================================================================= +// Platform detection +// +// Using boolean logic on predefined compilers variables, detect and set +// PLATFORM preprosessor defines to the unique ID specified above. +// +// The following definitions are set in this section: +// +// OS The OS +// COMP The compiler +// +// PLEASE NOTE: Do not set any preprocessor variable other than the above three in this +// section. Use the following sections for anything that does not fall into +// the above catagories. + +#if defined(_WIN32) + #define OS OS_WIN32 + + #if defined(_MSC_VER) + #define COMP COMP_MSVC + #else + #error _MSC_VER not defined. MSVC is currently the only supported compiler + #endif + +#elif defined(_IRIX) + #define OS OS_IRIX + #define COMP COMP_KAI_IRIX + +#elif defined(_ALPHA) + #define OS OS_OSF1 + #define COMP COMP_KAI_OSF1ALPHA + +#elif defined (_HPUX) + #define OS OS_HPUX + #define COMP COMP_KAI_HPANSIC + +#else +// OK for OS not to resolve, it's being phased out. +// #error Unknown OS +#endif + +#if !defined(OS) +// OK for OS not to resolve, it's being phased out. +// #error OS definition did not resolve. Check "platform.h". +#endif + /* XXX: COMP may now not resolve, because autoconf may + * detect GCC. This is done in the hopes that all + * COMP detections, and indeed both OS & COMP detechtions + * will eventualy be done automatically. + * + * This means, the former "#if !defined(COMP)" will + * temporarily have to also check the HAVE_[compiler] + * #defines until all compilers are checked by autoconf, + * at which point this can be removed completely. + * + * PH - 20010311 + */ +#if !defined(COMP) && !defined(HAVE_GCC) + #error COMP definition did not resolve. Check "platform.h". +#endif + +//============================================================================= +// Platform Macros (a.k.a. "IS_" macros) +// +// These macros are the "worker bees" of platform.h. Programmers should use +// these macros rather than comparing PLATFORM to the unique IDs by hand. +// +// NB: Programmers are STRONGLY ENCOURAGED not to use the OS detection macros +// or compiler detection marcros directly. Instead they should create +// macros specific to the task at hand. For example Win32 and Solaris support +// extended permissions for their files. Rather than check IS_WIN32 || IS_SOLARIS, +// create a new macro called "HAS_EXTENDED_FILE_PERMISSIONS" and use that. +// +// One case where it is reasonable to use the IS_WIN32 or IS_UNIX is when +// you need to protect a #include that is specific to a platform. +// +// Example usage: +// +// #ifdef WORDS_BIGENDIAN +// int network_order = machine_order; +// #else +// int network_order = swap(machine_order); +// #endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// OS detection +// Note: Avoid using these if possible (see above) +#define IS_WIN32 (OS == OS_WIN32) +#define IS_AIX (OS == OS_AIX) +#define IS_HPUX (OS == OS_HPUX) +#define IS_IRIX (OS == OS_IRIX) +#define IS_OSF1 (OS == OS_OSF1) + +// complier detection +#define IS_KAI (COMP == COMP_KAI_GCC || COMP == COMP_KAI_SUNPRO || COMP == COMP_KAI_GLIBC || COMP == COMP_KAI_VISUALAGE || COMP == COMP_KAI_HPANSIC || COMP == COMP_KAI_IRIX || COMP == COMP_KAI_OSF1ALPHA) +#define IS_MSVC (COMP == COMP_MSVC) +#define IS_SUNPRO (COMP == COMP_SUNPRO) + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// Unicode +#define SUPPORTS_UNICODE IS_WIN32 // The OS supports Unicode + +// KAI 3.4 uses a much improved stl +#define IS_KAI_3_4 (IS_KAI && (COMP == COMP_KAI_IRIX || COMP == COMP_KAI_OSF1ALPHA || COMP == COMP_KAI_GLIBC)) + +// Used in twlocale +#define USE_STD_CPP_LOCALE_WORKAROUND (IS_SUNPRO || (IS_KAI && !IS_KAI_3_4)) // TODO:BAM -- name this something more general. +#define USE_CLIB_LOCALE IS_KAI || HAVE_GCC +#define USES_CLIB_DATE_FUNCTION ( USE_CLIB_LOCALE || IS_SUNPRO || IS_MSVC ) // if we use clib, can't use C++ time_put, and SUNPRO and MSVC add characters +//#define USE_CLIB_LOCALE (IS_ALPHA || IS_IRIX || (IS_KAI && !IS_KAI_3_4)) + +// Threading API +// TODO:mdb -- this is not complete or rigorous on the unix side!!! +#define SUPPORTS_WIN32_THREADS IS_WIN32 +#define SUPPORTS_POSIX_THREADS (!SUPPORTS_WIN32_THREADS) + +// Miscellaneous +#define FSEEK_TAKES_INT32 IS_UNIX // True if fseek takes 32-bit offsets +#define USE_OUTPUT_DEBUG_STRING IS_WIN32 // Use the Win32 OutputDebugString() for debug messages. +#define SUPPORTS_MAPI IS_WIN32 +#define WCHAR_IS_16_BITS IS_WIN32 +#define WCHAR_IS_32_BITS IS_UNIX +#define WCHAR_REP_IS_UCS2 IS_WIN32 +#define USES_MPOPEN IS_UNIX +#define USES_WINSOCK IS_WIN32 +#define SUPPORTS_WCHART IS_WIN32 // TODO: Remove after getting new ver of KAI +#define USES_GLIBC ((COMP == COMP_KAI_GLIBC) || HAVE_GCC) +#define SUPPORTS_EVENTLOG IS_WIN32 +#define SUPPORTS_MEMBER_TEMPLATES ( ! IS_SUNPRO ) +#define SUPPORTS_EXPLICIT_TEMPLATE_FUNC_INST ( ! IS_SUNPRO ) + +//============================================================================= +// Miscellaneous +// +// Put all items that are not an "IS_" macro here. + +#if IS_BYTE_ALIGNED + #define BYTE_ALIGN 8 +#else + #error Unknown Byte alignment +#endif + +// A scalar that matches the sizeof a pointer +typedef unsigned long ptr_size_type; // true for all of our current platforms + // TODO: I would like to use a XXXX_t like name + +// Check integer representation +#if !(USES_2S_COMPLEMENT) + #error "Tripwire will only work on a 2's complement CPU. Check \"platform.h\"." +#endif + + + + +#endif // __PLATFORM_H + diff --git a/src/core/platform_t.cpp b/src/core/platform_t.cpp new file mode 100644 index 0000000..34bfde0 --- /dev/null +++ b/src/core/platform_t.cpp @@ -0,0 +1,225 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// platform_t.cpp +// +// test some platform assumptions + +#include "stdcore.h" +#include "platform.h" +#include "test/test.h" +#include "error.h" + +using namespace std; + +///////////////////////////////////////////////////////// +// UTIL FUNCTION PROTOTYPES +///////////////////////////////////////////////////////// +void TestAlignment(); +void TestSizes(); + +///////////////////////////////////////////////////////// +// TEMPLATIZED UTIL FUNCTION PROTOTYPES +///////////////////////////////////////////////////////// +template< class E, class T > +bool CanBeRepresentedAs( E e, T t ); + +///////////////////////////////////////////////////////// +// TEMPLATIZED UTIL CLASSES DECLARATIONS +///////////////////////////////////////////////////////// + +// Constructing this class will write to a memory location +// offset by ALIGN_SIZE. If it chokes, you'll get a bus error +template +class AlignMe +{ + public: + AlignMe(); + private: + byte a[sizeof(int64)+ALIGN_SIZE]; // we want to be able to access a int64 at address [ALIGN_SIZE] +}; + +///////////////////////////////////////////////////////// +// MAIN TEST FUNCTION +///////////////////////////////////////////////////////// + +void TestPlatform() +{ + TestAlignment(); + TestSizes(); +} + +///////////////////////////////////////////////////////// +// TEMPLATIZED UTIL CLASSES IMPLEMENTATIONS +///////////////////////////////////////////////////////// + +template +AlignMe::AlignMe() +{ + TCOUT << _T("Testing alignment of size ") << ALIGN_SIZE << std::endl; + + // access a double in the byte array to see if it is aligned. if it isn't and the CPU + // can't handle it, you'll get a bus error + + // this should choke if the CPU can't + // handle misaligned memory access + int32* pi = (int32*)&a[ALIGN_SIZE]; + TCOUT << _T("Testing alignment of an int32...") << std::endl; + TCOUT << _T("Reading...") << std::endl; + int32 i = *pi; // access memory for read + TCOUT << _T("Read succeeded.") << std::endl; + TCOUT << _T("Writing...") << std::endl; + *pi = i; // access memory for write + TCOUT << _T("Write succeeded.") << std::endl; + + // this should choke if the CPU can't + // handle misaligned memory access + int64* pb = (int64*)&a[ALIGN_SIZE]; + TCOUT << _T("Testing alignment of an int64...") << std::endl; + TCOUT << _T("Reading...") << std::endl; + int64 I = *pb; // access memory for read + TCOUT << _T("Read succeeded") << std::endl; + TCOUT << _T("Writing...") << std::endl; + *pb = I; // access memory for write + TCOUT << _T("Write succeeded.") << std::endl; + + TCOUT << _T("Alignment of ") << ALIGN_SIZE << _T(" ") << ( ALIGN_SIZE == 1 ? _T("byte") : _T("bytes") ) << _T(" is OK") << std::endl + << _T("=========================================\n"); +} + + +///////////////////////////////////////////////////////// +// UTIL FUNCTIONS +///////////////////////////////////////////////////////// + +void TestAlignment() +{ + // - - - - - - - - - - - - - - - - - - - - - - + // empirically determine byte alignment -- see AlignMe definition + // The last AlignMe to be successfully constructed + // - - - - - - - - - - - - - - - - - - - - - - + + TCOUT << _T("Testing for byte alignment\n") + << _T("=========================================\n"); + + AlignMe<128> a128; + AlignMe<64> a64; + AlignMe<32> a32; + AlignMe<16> a16; + AlignMe<8> a8; + AlignMe<4> a4; + AlignMe<2> a2; + AlignMe<1> a1; + + // - - - - - - - - - - - - - - - - - - - - - - + // test a misaligned memory access -- if this + // chokes, your CPU can't handle such accesses + // (if it works, your CPU may still not handle + // such accesses: it may have handled the + // hardware interrupt that might have occured. + // - - - - - - - - - - - - - - - - - - - - - - + byte a[sizeof(int32)+sizeof(byte)]; + + // this should be fine + a[0] = 0xAB; + + + TCOUT << _T("=========================================\n") + << _T("About to test memory access off by 1 byte\n") + << _T("If you do not see a confirmation after this line, the test choked") + << std::endl; + + // this should choke if the CPU can't + // handle misaligned memory access + int32* pi = (int32*)&a[1]; + *pi = *pi; // misaligned access (read and write) + + TCOUT << _T("Misaligned access OK.") << std::endl; + + // - - - - - - - - - - - - - - - - - - - - - - + // make sure our BYTE_ALIGN value is correct -- + // OK, if the above test failed, then comment it out and try this one. + // if it works, then our BYTE_ALIGN value is large enough + // - - - - - - - - - - - - - - - - - - - - - - + + byte b[2*sizeof(BYTE_ALIGN)]; + + // this should be fine + b[0] = 0xAB; + + TCOUT << _T("=========================================\n") + << _T("About to test memory access off by ") << BYTE_ALIGN + << _T(" ") << ( BYTE_ALIGN == 1 ? _T("byte") : _T("bytes") ) << std::endl + << _T("If you do not see a confirmation after this line, the test choked") + << std::endl; + + // this should choke if the CPU can't + // handle misaligned memory access + pi = (int32*)&b[BYTE_ALIGN]; + *pi = *pi; // aligned (hopefully) access (read and write) + + TCOUT << _T("Aligned access OK. BYTE_ALIGN value of ") << BYTE_ALIGN << _T(" is good.") << std::endl; + TCOUT << _T("=========================================\n"); +} + +void TestSizes() +{ + /* + ASSERT( CanBeRepresentedAs( char(), char() ) ); + ASSERT( CanBeRepresentedAs( char(), unsigned char() ) ); + ASSERT( CanBeRepresentedAs( unsigned char(), char() ) ); + ASSERT( CanBeRepresentedAs( unsigned char(), unsigned char() ) ); + ASSERT( CanBeRepresentedAs( signed char(), char() ) ); + ASSERT( CanBeRepresentedAs( char(), signed char() ) ); + ASSERT( CanBeRepresentedAs( signed char(), signed char() ) ); + ASSERT( CanBeRepresentedAs( signed char(), unsigned char() ) ); + ASSERT( CanBeRepresentedAs( char(), signed char() ) ); + */ +} + +///////////////////////////////////////////////////////// +// TEMPLATIZED UTIL FUNCTION IMPEMENTATIONS +///////////////////////////////////////////////////////// + +template< class E, class T > +bool CanBeRepresentedAs( E e, T t ) +{ + ASSERT( std::numeric_limits< E >::is_specialized ); + ASSERT( std::numeric_limits< T >::is_specialized ); + + bool fReturn = true; + + fReturn &= ( std::numeric_limits< E >::min() >= std::numeric_limits< T >::min() ); + fReturn &= ( std::numeric_limits< E >::max() <= std::numeric_limits< T >::max() ); + + return fReturn; +} diff --git a/src/core/refcountobj.cpp b/src/core/refcountobj.cpp new file mode 100644 index 0000000..3755361 --- /dev/null +++ b/src/core/refcountobj.cpp @@ -0,0 +1,155 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// refcountobj.cpp +#include "stdcore.h" + +#include "refcountobj.h" +#include "debug.h" + +// TODO:dmb - not sure about commenting this out, do we want to include ??? +//#include "typeinfo.h" + +#include "errorutil.h" + +#ifdef _DEBUG +int cRefCountObj::objectCounter = 0; +int cRefCountObj::referenceCounter = 0; + +#include +// ok, this is getting serious! +#include +typedef std::set RefSet; // collection of addresses of all reference counted objects +RefSet* gpRefCountObj_Objects = 0; + +// a way to see what hasn't been accounted for.... +struct cRefCountObj_Debug +{ + ~cRefCountObj_Debug() + { + RefSet::iterator i; + cDebug d("cRefCountObj_Debug"); + if(gpRefCountObj_Objects) + { + for(i = gpRefCountObj_Objects->begin(); i != gpRefCountObj_Objects->end(); i++) + { + d.TraceNever("Refrence Counted Object %p still exists\n", *i); + } + } + } +} gRefCountObj_Debug; + +#endif // _DEBUG + +cRefCountObj::cRefCountObj() +{ + mRefCount = 1; + +//std::cout << "Allocated RefObj(" << std::hex << (int)this << ")\n"; + +#ifdef _DEBUG + ++objectCounter; + ++referenceCounter; + + cDebug d("cRefCountObj::cRefCountObj"); + d.TraceNever("Object Created[%p] %s\n", this, typeid(*this).name()); + + if(! gpRefCountObj_Objects) + gpRefCountObj_Objects = new RefSet; + gpRefCountObj_Objects->insert(this); +#endif +} + +cRefCountObj::~cRefCountObj() +{ + ASSERT(mRefCount == 0); + +//std::cout << "Deleted RefObj(" << std::hex << (int)this << ")\n"; + +#ifdef _DEBUG + --objectCounter; + cDebug d("cRefCountObj::~cRefCountObj"); + d.TraceNever("Object Destroyed[%p] %s Objects Left = %d\n", this, typeid(*this).name(), objectCounter); + if(objectCounter == 0) + { + d.TraceDebug("****** All Reference Counted Objects Destroyed! ******\n") ; + } + + ASSERT(gpRefCountObj_Objects); + RefSet::const_iterator i = gpRefCountObj_Objects->find(this); + ASSERT(i != gpRefCountObj_Objects->end()); + gpRefCountObj_Objects->erase(this); + if(gpRefCountObj_Objects->size() == 0) + { + delete gpRefCountObj_Objects; + gpRefCountObj_Objects = 0; + } + +#endif +} + +void cRefCountObj::AddRef() const +{ + ASSERT(this); + + if (mRefCount <= 0) + { + THROW_INTERNAL("refcountobj.cpp"); + } + + ++mRefCount; + + #ifdef _DEBUG + ++referenceCounter; + #endif +} + +void cRefCountObj::Release() const +{ + if (this == 0) + return; + + if (--mRefCount == 0) + { + Delete(); + } + + #ifdef _DEBUG + --referenceCounter; + #endif +} + +void cRefCountObj::Delete() const +{ + delete this; +} + diff --git a/src/core/refcountobj.h b/src/core/refcountobj.h new file mode 100644 index 0000000..7a716e5 --- /dev/null +++ b/src/core/refcountobj.h @@ -0,0 +1,94 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// refcountobj.h +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __REFCOUNTOBJ_H +#define __REFCOUNTOBJ_H + +/////////////////////////////////////////////////////////////////////////////// +// class cRefCountObj +// +// Base class for objects that are to be reference counted. Derive from this +// class to create an object that will keep track of how many owners it has +// and will delete itself when it runs out of owners. +// +// The convention for using this class it to call AddRef() when you pass +// a pointer to the object to a new owner. When the new owner is done with +// the object it +// +// Note: In the current implementation we do not support a reference counted +// object being an owner of itself, either directly or indirectly. For instance +// if you make a cRefCountObj capable of being an owner of a cRefCountObj* (say +// through some AddChild(cRefCountObj*) function) and then call AddRef() followed +// by AddChild(), then call Release(), you will end up with an object of reference +// count 1 but no owners outside itself. +// +// This is not foreseen to be a problem with the tripwire usage of this class. +// +// See refcountobj_t.cpp for examples on use. +// + +class cRefCountObj +{ +public: + cRefCountObj(); + + virtual void AddRef() const; + virtual void Release() const; + + int GetRefCount() const { return mRefCount; } + // sometimes it is useful to know an object's refrence +protected: + virtual ~cRefCountObj(); + + virtual void Delete() const; + // override this if you don't want to be destroyed by "delete this"! +private: + mutable int mRefCount; + +#ifdef _DEBUG +private: + static int objectCounter; + static int referenceCounter; + friend void TestRefCountObj(); +public: + static bool AllRefCountObjDestoryed() + { + return objectCounter == 0 && referenceCounter == 0; + } +#endif +}; + +#endif + diff --git a/src/core/refcountobj_t.cpp b/src/core/refcountobj_t.cpp new file mode 100644 index 0000000..d9502ff --- /dev/null +++ b/src/core/refcountobj_t.cpp @@ -0,0 +1,167 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// + +#include "stdcore.h" +#include "refcountobj.h" +#include "debug.h" + +class cRefCountTestObj : public cRefCountObj +{ +public: + cRefCountTestObj(); + + virtual void Release(); + + void AddChild(cRefCountTestObj* pChild); + +private: + virtual ~cRefCountTestObj(); + + std::list mChildren; + int8* mpSomeMem; +}; + +cRefCountTestObj::cRefCountTestObj() +{ + // allocate some mem that should be caught + // by the memory manager if this object does not + // get destructed. + mpSomeMem = new int8[10]; +} + +cRefCountTestObj::~cRefCountTestObj() +{ + while (!mChildren.empty()) + { + mChildren.front()->Release(); + mChildren.pop_front(); + } + + delete mpSomeMem; +} + +void cRefCountTestObj::AddChild(cRefCountTestObj* pChild) +{ + mChildren.push_back(pChild); +} + +void cRefCountTestObj::Release() +{ + cRefCountObj::Release(); +} + +// -- + +class cRefCountTestObjList +{ +public: + cRefCountTestObjList(); + ~cRefCountTestObjList(); + + void Add(cRefCountTestObj* pNewObj); + + std::list mList; +}; + +cRefCountTestObjList::cRefCountTestObjList() +{ +} + +cRefCountTestObjList::~cRefCountTestObjList() +{ + while(!mList.empty()) + { + mList.front()->Release(); + mList.pop_front(); + } +} + +void cRefCountTestObjList::Add(cRefCountTestObj* pNewObj) +{ + mList.push_back(pNewObj); +} + + +/////////////////////////////////////////////////////////////////////////////// + +void TestRefCountObj() +{ + cDebug db("TestRefCountObj()"); + + db.TraceAlways("Entering...\n"); + + // Note the following test of Reference counted objects containing + // copies of themselves failed. Perhaps someday we will upgrade the + // reference counting interface to allow this type of structure. + /* + cRefCountTestObj* pObj1 = new cRefCountTestObj; + cRefCountTestObj* pObj2 = new cRefCountTestObj; + pObj1->AddChild(pObj2); + pObj1->AddRef(); + pObj2->AddChild(pObj1); + pObj1->Release(); + + ASSERT(cRefCountObj::objectCounter == 0); + ASSERT(cRefCountObj::referenceCounter == 0); + */ + + int i; + { + cRefCountTestObjList list1, list2, list3; + + for (i = 0; i < 3; ++i) + list1.Add(new cRefCountTestObj); + + std::list::iterator itr; + for (itr = list1.mList.begin(); itr != list1.mList.end(); ++itr) + { + (*itr)->AddRef(); + list2.Add(*itr); + } + + for (itr = list2.mList.begin(); itr != list2.mList.end(); ++itr) + { + (*itr)->AddRef(); + list3.Add(*itr); + if (++itr == list2.mList.end()) + break; + } + } + + ASSERT(cRefCountObj::objectCounter == 0); + ASSERT(cRefCountObj::referenceCounter == 0); + + db.TraceAlways("Done...\n"); + + return; +} + diff --git a/src/core/resources.h b/src/core/resources.h new file mode 100644 index 0000000..27923be --- /dev/null +++ b/src/core/resources.h @@ -0,0 +1,548 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: resources.h +// Date....: 05/06/99 +// Creator.: Robert DiFalco (rdifalco) +// +// Abstraction for a keyed collection of resources including a +// specialization for dealing with message resources. +// + +#ifndef __RESOURCES_H +#define __RESOURCES_H + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include // for: Resource Table Implementation +#include "debug.h" // for: ASSERT and Trace +#include "error.h" // for: eInternal + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Classes Declared in this module +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template< class KEY, class RSC > class cResources_; +template< class KEY, class CHR > class cMessages_; + + +//============================================================================= +// cResources_ -- Keyed collection of resources +//----------------------------------------------------------------------------- +// SYNOPSIS: +// Used to maintain a table of resources that are indexed by KEY +// type values. The type can be any valid type that is +// assignable. +// +// CONSTRAINTS: +// must be a valid key type for the std::map concept +// must be a valid value type for the std::map concept. +// +// INVARIANTS: +// +// +template< class KeyT, class RscT > +class cResources_ +{ + //--Type Definitions + + private: + + typedef + std::map< KeyT, RscT > Table; // Storage Rep + + + public: + + // Type definitions + + typedef KeyT Key; // The resource id + typedef KeyT& KeyRef; + typedef const KeyT& ConstKeyRef; + + typedef RscT Value; // The managed resource + typedef Value& ValueRef; + typedef const Value& ConstValueRef; + + typedef typename Table::value_type Pair; + + + + //--Interface. + + public: + + // Observers + + ConstValueRef Get( ConstKeyRef ) const; + + + // Modifiers + + void Put( const Pair*, const Pair* ); + void Put( ConstKeyRef, Value ); + + + //--Implementation. + + protected: + + static ConstValueRef DefaultValueRef(); // NOTE: + + private: + + Table m_table; +}; + + + +//============================================================================= +// cMessages_ -- Specialization of Resources_ for message strings +//----------------------------------------------------------------------------- +// SYNOPSIS: +// Specialization of cResources_ to store message strings +// instead of generalized resource objects. In the future this can +// be refactored to use message objects so that they can come from +// a dynamic source (i.e., not a string-literal) such as persistant +// storage or some algorithm based on the concatenation of elements. +// The cMessages_ abstraction allows a program to be +// character type independent so that it may use ANSI, MBCS, or +// UNICODE within the same application instance. This is achieved by +// not allowing the client to expect a specific character sequence +// representation, such as the near ubiquitous const char*. For +// example: +// +// const char* psz = messages.GetAnsi( IDS_SOMESTRING ); +// +// The above call requires the caller to be responsible for memory +// resources in the case of a conversion. However, there is no +// clear way to know up front how many bytes will be required. +// Another equally unsatisfactory solution is to allocate the +// memory within cMessages and require the caller to release the +// the resources when they are done with the message. If we instead +// require calls in the following form: +// +// std::string str = messages.GetAnsi( IDS_SOMESTRING ); +// +// We can allows assume proper resource use regardless of whether +// a simple character pointer is returned or newly allocated +// resources used to convert the stored message. +// +// +// CONSTRAINTS: +// As with all classes which manipulate character sequences, CHAR +// must be a valid character type as defined by the STDCPP standard. +// +// +template< class KeyT, class CharT > +class cMessages_ : public cResources_< KeyT, const CharT* > +{ + //--Type definitions + + protected: + + typedef + cResources_ + Resources; + + public: + + typedef std::basic_string String; + typedef const KeyT& ConstKeyRef; + + + //--Interface. + + public: + + String Get ( ConstKeyRef ) const; + std::string GetAnsi( ConstKeyRef ) const; +#if SUPPORTS_WCHART + std::wstring GetWide( ConstKeyRef ) const; +#endif//SUPPORTS_WCHART +}; + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// IMPLEMENTATION: cResources_ +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// NOTE: Macros to ease any changes in template arguments + +#define Resource_Template template< class KeyT, class RscT > +#define Resource_Class cResources_< KeyT, RscT > + + +Resource_Template +void Resource_Class::Put( const Pair* beg, const Pair* end ) +{ + for ( const Pair* at = beg; at != end; ++at ) + { + if ( !m_table.insert( *at ).second ) + { + ASSERTMSG( 0, "Resource key already exists!" ); + // throw eInternal( "Resource key already exists!" ); + } + } +} + +// By value allows the user to Resource_table.Put( 6, "Literal" ); +Resource_Template +inline +void Resource_Class::Put( ConstKeyRef id, Value sResource ) +{ + if ( m_table.insert( Pair( id, sResource ) ).second == false ) + { + ASSERTMSG( 0, "Resource key already exists!" ); + // throw eInternal( "Resource key already exists!" ); + } +} + +Resource_Template +typename Resource_Class::ConstValueRef +Resource_Class::Get( ConstKeyRef id ) const +{ + typename Table::const_iterator at = m_table.find( id ); + + if ( at == m_table.end() ) + { + #if IS_UNIX + #ifdef _DEBUG + std::cerr << "*** Error Resource_Class::Get() [" __FILE__ ":" << __LINE__ << "]: Resource not found\n"; + #endif + #else + ASSERTMSG( 0, "Resource does not exist!" ); + #endif + // TSS_Raise( eInternal, "Resource does not exist!" ); + + return DefaultValueRef(); + } + else + { + return (*at).second; + } +} + +Resource_Template +typename Resource_Class::ConstValueRef +Resource_Class::DefaultValueRef() +{ + static Value _default; + return _default; +} + + +#undef Resource_Template //template< class KeyT, class RscT > +#undef Resource_Class //Resources_ + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// IMPLEMENTATION: cMessages_ +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// NOTE: Macros to ease any changes in template arguments + +#define Message_Template template< class KeyT, class CharT > +#define Message_Class cMessages_< KeyT, CharT > + + +Message_Template +inline +typename Message_Class::String +Message_Class::Get( ConstKeyRef id ) const +{ + typename Message_Class::Value msg = Resources::Get( id ); + return + ( msg == this->DefaultValueRef() ) + ? String() + : String( msg ); +} + + +/// NOTE: Can't have anonymous NS in Headers + +namespace tss +{ + namespace rsc + { + /* WARNING:RAD -- Cannot use StringUtil or CodeConvert since + these use ErrorMessages and String Resources! */ + + inline + void + ToNTMBS( std::string& nbs, const std::string& src ) + { + nbs.assign( src ); + } + + #if SUPPORTS_WCHART + + inline + void + ToNTMBS( std::string& nbs, const std::wstring& wcs ) + { + nbs.resize( MB_CUR_MAX * wcs.size() ); + + size_t nWrote = + ::wcstombs( + const_cast< char * >( nbs.c_str() ), + wcs.c_str(), nbs.size() + 1 ); + + if ( nWrote == (size_t)-1 ) + { + ASSERTMSG( false, "Conversion error in cMessages_!" ); + // throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + nbs.resize( nWrote ); + } + + inline + void + ToNTWCS( std::wstring& dst, const std::wstring& src ) + { + dst.assign( src ); + } + + inline + void + ToNTWCS( std::wstring& wcs, const std::string& nbs ) + { + wcs.resize( nbs.size() ); + + size_t nWrote = + ::mbstowcs( + const_cast< wchar_t * >( wcs.c_str() ), + nbs.c_str(), wcs.size() + 1 ); + + if ( nWrote == (size_t)-1 ) + { + ASSERTMSG( false, "Conversion error in cMessages_!" ); + // throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + wcs.resize( nWrote ); + } + #endif//SUPPORTS_WCHART + }//rsc:: +}//tss:: + + +Message_Template +inline +std::string +Message_Class::GetAnsi( ConstKeyRef id ) const +{ + typename Message_Class::Value msg = Resources::Get( id ); + + if ( msg == this->DefaultValueRef() ) + { + return std::string(); + } + else + { + std::string nbs; + tss::rsc::ToNTMBS( nbs, String( msg ) ); + return nbs; + } +} + + +#if SUPPORTS_WCHART + +Message_Template +inline +std::wstring +Message_Class::GetWide( ConstKeyRef id ) const +{ + Value msg = Resources::Get( id ); + + if ( msg == DefaultValueRef() ) + { + return std::string(); + } + else + { + std::wstring wcs; + tss::rsc::ToNTWCS( wcs, String( msg ) ); + return wcs; + } +} + +#endif//SUPPORTS_WCHART + + +#undef Message_Template +#undef Message_Class + +#endif//__RESOURCES_H + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef RAD_OLDCODE + +//============================================================================= +// cMessages_ -- Specializations +//----------------------------------------------------------------------------- +// SYNOPSIS: +// MSVC does not yet support specializations. As a compromise, we fully +// specialize on TCHR but assume a key type of "const int". +// + +// for SUNPro enums are ints, not const ints +#if IS_SUNPRO + #define ENUM_TYPE int +#else + #define ENUM_TYPE const int +#endif + +template<> +class cMessages_ : + public cResources_< ENUM_TYPE, const char* > +{ + protected: + + typedef + cResources_< ENUM_TYPE, const char* > + Resources; + + public: + + typedef std::string String; + typedef int ConstKeyRef; // Better than + + + String Get( ConstKeyRef id ) const + { + Value msg = Resources::Get( id ); + return ( msg != DefaultValueRef() ) + ? String( msg ) + : String(); + } + + String GetAnsi( ConstKeyRef id ) const + { + return Get( id ); + } + +#if SUPPORTS_WCHART + std::wstring GetWide( ConstKeyRef id ) const + { + Value msg = Resources::Get( id ); + + if ( msg == DefaultValueRef() ) + { + return std::wstring(); + } + else + { + String::size_type + N = String::traits_type::length( msg ); + + std::wstring dst( N, 0x00 ); + std::ctype< wchar_t >().widen( msg, msg + N, dst.begin() ); + + return dst; + } + } +#endif//SUPPORTS_WCHART +}; + +#if SUPPORTS_WCHART + +template<> +class cMessages_ : + public cResources_< const int, const wchar_t* > +{ + protected: + + typedef + cResources_ + Resources; + + public: + + typedef std::wstring String; + typedef int ConstKeyRef; // Better than + + + String Get( ConstKeyRef id ) const + { + Value msg = Resources::Get( id ); + if( msg != DefaultValueRef() ) + return String( msg ); + else + return String(); + } + + std::string GetAnsi( ConstKeyRef id ) const + { + Value msg = Resources::Get( id ); + + if ( msg == DefaultValueRef() ) + { + return std::string(); + } + else + { + String::size_type + N = String::traits_type::length( msg ); + + std::string dst( N, 0x00 ); + std::ctype().narrow( msg, msg + N, '?', dst.begin() ); + + return dst; + } + } + + String GetWide( ConstKeyRef id ) const + { + return Get( id ); + } +}; + +#endif//SUPPORTS_WCHART + +#endif//RAD_OLDCODE + + diff --git a/src/core/resources_t.cpp b/src/core/resources_t.cpp new file mode 100644 index 0000000..420d907 --- /dev/null +++ b/src/core/resources_t.cpp @@ -0,0 +1,100 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: tss.resources_t.cpp +* Date....: 05/04/99 +* Creator.: Robert DiFalco (rdifalco) +*/ + +#include "stdcore.h" +#include "package.h" +#include "test/test.h" +#include + + +TSS_BeginPackage( cTestResources ) + + TSS_DECLARE_STRINGTABLE; + + public: + + cTestResources() : mnCount( 10 ) + { + } + + size_t Count() const { + return mnCount; + } + + size_t Count( size_t nCount ) { + return mnCount = nCount; + } + + private: + size_t mnCount; + +TSS_EndPackage( cTestResources ) + +TSS_BeginStringIds( test ) + IDS_TEST1 = 1, + IDS_TEST2, + IDS_TEST3, + IDS_INVALID +TSS_EndStringIds( test ) + +TSS_BeginStringtable( cTestResources ) + TSS_StringEntry( test::IDS_TEST1, _T("Test String 1") ), + TSS_StringEntry( test::IDS_TEST2, _T("Test String 2") ), + TSS_StringEntry( test::IDS_TEST3, _T("Test String 3") ) +TSS_EndStringtable( cTestResources ) + + + +TSS_ImplementPackage( cTestResources ) + +void TestResources() +{ + TSS_Package( cTestResources ).Count( 20 ); + + TCOUT << _T("Package::Count(") << TSS_Package( cTestResources ).Count() << _T(")\n" ) << std::endl; + + TCOUT << TSS_GetString( cTestResources, test::IDS_TEST1 ) << std::endl; + TCOUT << TSS_GetString( cTestResources, test::IDS_TEST2 ) << std::endl; + TCOUT << TSS_GetString( cTestResources, test::IDS_TEST3 ) << std::endl; + TCOUT << TSS_GetString( cTestResources, test::IDS_INVALID ) << std::endl; + + +} + + +// eof: tss.resources_t.cpp + diff --git a/src/core/serializable.cpp b/src/core/serializable.cpp new file mode 100644 index 0000000..7c559df --- /dev/null +++ b/src/core/serializable.cpp @@ -0,0 +1,43 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializer.cpp -- The object that does the serialization work. +/////////////////////////////////////////////////////////////////////////////// +#include "stdcore.h" +#include "serializable.h" + +#if IS_SUNPRO +iTypedSerializable::~iTypedSerializable() {} +iSerializable::~iSerializable() {} +iTyped::~iTyped() {} +#endif + diff --git a/src/core/serializable.h b/src/core/serializable.h new file mode 100644 index 0000000..f9e61a2 --- /dev/null +++ b/src/core/serializable.h @@ -0,0 +1,129 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializable.h -- the serializable interface +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SERIALIZABLE_H +#define __SERIALIZABLE_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TYPED_H +#include "typed.h" +#endif + +class iSerializer; + +// Some version documentation is in order here: +// +// Objects that derive from iSerializable do not need to worry about versions, they +// should just read and write themselves to and from the serializer. +// +// Objects that wish to implement versioning should derive themselves from iTypedSerializerable. +// They should use the IMPLEMENT_TYPEDSERIALIZABLE() macro to declare their major and minor +// version number. Neither major or minor version number can be negative and at least one +// must be greater than zero. +// +// When an object is serialized using iSerializer::WriteObject() a header will be written that +// includes the current version number will be saved in the archive by. Therefore +// iSerializable::Write() implementations do not need to worry about versioning, They need only +// write out the object in current format. +// +// When an object is read back from an archive using iSerializer::ReadObject(), +// the version of the serialized object will be read from the header and is passed to +// iSerializable::Read(). Each implementation of Read() should this passed in version. +// If the version is greater than the current version Read() should throw a eSerializer +// exception. If the version is older than the current implementation, Read() should either +// read the older format or throw an eSerializer exception. +// +// IMPORTANT: If the version is 0 (the default parameter) then Read() it should read +// in the current format of the object. This is important if Read() is called directly. +// +// In some cases it may be desirable to not incur the overhead of the serializer writing +// header information for each serialized object. In this case call iSerializable::Read() and +// iSerializable::Write() directly rather than using ReadObject() and WriteObject(). + +class iSerializable +{ +public: + virtual void Read (iSerializer* pSerializer, int32 version = 0) = 0; // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const = 0; // throw (eSerializer, eArchive) + // objects implement these methods to read and write themselves to a serializer. + + #ifdef _SUNPRO + ~iSerializable(); + #endif +}; + +class iTypedSerializable : public iTyped, public iSerializable +{ +public: + typedef iTypedSerializable* (*CreateFunc)(); + // Pointer to a function that creates an empty version of each typed serializable object + + virtual int32 Version() const = 0; + // Return the current version of that this serializable object writes. + // As a convention version number should be (major_version << 16) | minor_version. + + static int32 MkVersion(int16 major, int16 minor) { return (int32)(((uint32)major << 16) | (uint32)minor); } + static int16 MajorVersion(int32 version) { return (int16)((uint32)version >> 16); } + static int16 MinorVersion(int32 version) { return (int16)version; } + + #ifdef _SUNPRO + ~iTypedSerializable(); + #endif +}; + +////////////////////////////// +// convenience macros +#define DECLARE_TYPEDSERIALIZABLE() \ + DECLARE_TYPED() \ +public: \ + static iTypedSerializable* Create(); \ + virtual int32 Version() const; + +#define IMPLEMENT_TYPEDSERIALIZABLE(CLASS, TYPEDSTRING, VERSION_MAJOR, VERSION_MINOR) \ + IMPLEMENT_TYPED(CLASS, TYPEDSTRING) \ + iTypedSerializable* CLASS::Create() \ + { \ + return new CLASS; \ + } \ + int32 CLASS::Version() const \ + { \ + return iTypedSerializable::MkVersion(VERSION_MAJOR, VERSION_MINOR); \ + } + +#endif // __SERIALIZABLE_H + diff --git a/src/core/serializer.cpp b/src/core/serializer.cpp new file mode 100644 index 0000000..26d792d --- /dev/null +++ b/src/core/serializer.cpp @@ -0,0 +1,123 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializer.cpp -- The object that does the serialization work. +/////////////////////////////////////////////////////////////////////////////// +#include "stdcore.h" +#include "serializer.h" + +// TODO: May localizable strings need to be moved to string table + +//############################################################################# +// eSerializer +//############################################################################# + +/////////////////////////////////////////////////////////////////////////////// +// eSerializer::GetMsg -- Overloaded method for returning an error message. +/*virtual*/ TSTRING eSerializer::GetMsg() const +{ + TSTRING ret; + + if( !eSerializer::mDataSource.empty() ) + { + ret = mMsg; + + switch( eSerializer::mSourceType ) + { + case TY_UNDEFINED: + ret.append( mDataSource ); + break; + case TY_FILE: + ret.append( _T("\nFile: ") ); + ret.append( mDataSource ); + break; + case TY_TEMPFILE: + ret.append( _T("\nTemporary File: ") ); + ret.append( mDataSource ); + break; + case TY_MEMORY: + ret.append( _T("\nMemory Block: ") ); //uhhh...?? + ret.append( mDataSource ); + break; + case TY_PIPE: + ret.append( _T("\nNamed Pipe: ")); + ret.append( mDataSource ); + break; + case TY_SOCKET: + ret.append( _T("\nNetwork Socket: ")); + ret.append( mDataSource ); + break; + default: + ret.append( _T("\n")); + ret.append( mDataSource ); + break; + } + } + else + { + // Just use the base class method... + ret = eError::GetMsg(); + } + + return ret; +} + +/* +eSerializer::eSerializer(ErrorNum errNum, const TSTRING& msg) : + eError(errNum, msg) +{ +} + +const TSTRING& eSerializer::GetMsg() const +{ + if((mErrorNum < 0) || (mErrorNum >= E_NUMITEMS)) + { + // I don't know what this error number is; just use the base class implementation + return eError::GetMsg(); + } + + static TSTRING message; + static const TCHAR* reasonStrings[] = { _T("The serializer encountered an unknown type"), + _T("Invlaid input stream format for serializer"), + _T("Archive error"), + _T("Version Mismatch"), + _T("Invalid Reason") }; + + message = reasonStrings[mErrorNum]; + message += _T(" : "); + message += mMsg; + + return message; + +} + +*/ diff --git a/src/core/serializer.h b/src/core/serializer.h new file mode 100644 index 0000000..ec7ffcc --- /dev/null +++ b/src/core/serializer.h @@ -0,0 +1,163 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializer.h -- The object that does the serialization work. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SERIALIZER_H +#define __SERIALIZER_H + +#ifndef __ERROR_H +#include "error.h" +#endif + +class iTypedSerializable; +class iSerializable; + +//////////////////////////////////////////////////////////// +// Serializer Base Exception +//////////////////////////////////////////////////////////// +TSS_BEGIN_EXCEPTION_NO_CTOR( eSerializer, eError ) + // TODO: What else to add to this enumeration? Locked File? Temp file? + enum DataSourceType { + TY_UNDEFINED = 0, + TY_FILE, + TY_TEMPFILE, + TY_MEMORY, + TY_PIPE, + TY_SOCKET + }; + + eSerializer( const TSTRING& msg, const TSTRING& dataSource = _T(""), DataSourceType paramType = TY_UNDEFINED ) + : eError( msg ), + mDataSource( dataSource ), + mSourceType( paramType ) + {} + + virtual TSTRING GetMsg() const; + +private: + TSTRING mDataSource; + // TSTRING indentifier of the datasource associated with a particular error + // (if one exists) EX: a filename. + DataSourceType mSourceType; +TSS_END_EXCEPTION(); + +//////////////////////////////////////////////////////////// +// Helper Macro For Serializer Exceptions +//////////////////////////////////////////////////////////// +#define TSS_SERIALIZER_EXCEPTION( except ) \ + TSS_BEGIN_EXCEPTION_NO_CTOR( except, eSerializer ) \ + except( const TSTRING& msg, const TSTRING& dataSource = _T(""), DataSourceType paramType = TY_UNDEFINED ) \ + : eSerializer( msg, dataSource, paramType ) \ + {}; \ + TSS_END_EXCEPTION() + +//////////////////////////////////////////////////////////// +// Specific Exceptions +//////////////////////////////////////////////////////////// +TSS_SERIALIZER_EXCEPTION( eSerializerUnknownType ); +TSS_SERIALIZER_EXCEPTION( eSerializerInputStreamFmt); +TSS_SERIALIZER_EXCEPTION( eSerializerOutputStreamFmt ); +TSS_SERIALIZER_EXCEPTION( eSerializerInputStremTypeArray ); +TSS_SERIALIZER_EXCEPTION( eSerializerArchive ); // not used +TSS_SERIALIZER_EXCEPTION( eSerializerVersionMismatch ); +TSS_SERIALIZER_EXCEPTION( eSerializerEncryption ); + +/* + E_UNKNOWN_TYPE = 700, + E_INPUT_STREAM_FORMAT = 701, + E_OUTPUT_STREAM_FORMAT = 706, + E_INPUT_STR_TYPEARRAY = 702, // bad index in to type array + E_ARCHIVE = 703, + E_VERSION_MISMATCH = 704, + E_ENCRYPTION_ERROR = 705, +*/ + +class iSerializer +{ +public: + // Initializing and closing the archive + virtual void Init() = 0; // throw eSerializer + // initializes the serializer; must be called before any reading or writing is done + virtual void Finit() = 0; + // called after a session of serialization is done; called implicitely by the destructor + // if not called explicitely before destruction + + //Reading and writing objects Init() should have already been called or all these will fail. + virtual void WriteObjectDynCreate(const iTypedSerializable* pObj) = 0; // throw (eSerializer, eArchive) + // writes an object such that it can be dynamically created when read back in with + // ReadObject. + virtual iTypedSerializable* ReadObjectDynCreate() = 0; // throw (eSerializer, eArchive); + // reads an object from the archive, returning a pointer to it. The caller is responsible for + // deleteing or Release()ing it when done. + virtual void WriteObject(const iTypedSerializable* pObj) = 0; // throw (eSerializer, eArchive) + // writes an object to the archive that will not be dynamically created + virtual void ReadObject(iTypedSerializable* pObj) = 0; // throw (eSerializer, eArchive) + // reads an object that was written with WriteObject() + + + // writing interface + // all of these can throw eArchive + virtual void ReadInt16(int16& ret) = 0; + virtual void ReadInt32(int32& ret) = 0; + virtual void ReadInt64(int64& ret) = 0; + virtual void ReadString(TSTRING& ret) = 0; + virtual int ReadBlob(void* pBlob, int count) = 0; + virtual void WriteInt16(int16 i) = 0; + virtual void WriteInt32(int32 i) = 0; + virtual void WriteInt64(int64 i) = 0; + virtual void WriteString(const TSTRING& s) = 0; + virtual void WriteBlob(const void* pBlob, int count) = 0; + + virtual TSTRING GetFileName() const { return _T(""); } + // derived classes can implement this to return the file name associated with the serializer. + // it is only used in error reporting. + + // the error enumeration: 700-799 + enum ErrorNum + { + E_UNKNOWN_TYPE = 700, + E_INPUT_STREAM_FORMAT = 701, + E_INPUT_STR_TYPEARRAY = 702, // bad index in to type array + E_ARCHIVE = 703, + E_VERSION_MISMATCH = 704, + E_ENCRYPTION_ERROR = 705, + E_OUTPUT_STREAM_FORMAT = 706, + E_NUMITEMS + }; +}; + + + +#endif + diff --git a/src/core/serializer_t.cpp b/src/core/serializer_t.cpp new file mode 100644 index 0000000..0d78557 --- /dev/null +++ b/src/core/serializer_t.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializer_t.cpp -- Test the object that does the serialization work. +/////////////////////////////////////////////////////////////////////////////// + +//changed 7/6/99 -dra + +#include "stdcore.h" +#include "serializer.h" +#include "serializable.h" + +// The reading and writing functionality of the serializer is tested in +// serializerimpl_t.cpp, so there's very little to be done here. + +// Let's make a minimal test object just to make sure the interface is +// working properly... and then instantiate it. The actual implementation +// will be tested in serializerimpl_t.cpp +class cSerTestObject : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cSerTestObject(); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0) {} + virtual void Write(iSerializer* pSerializer) const {} + +private: + int mDummy; +}; + +IMPLEMENT_TYPEDSERIALIZABLE(cSerTestObject, _T("cSerTestObject"), 0, 1) + +cSerTestObject::cSerTestObject() +{ + mDummy = 0; +} + +void TestSerializer() +{ + cSerTestObject test_obj; +} diff --git a/src/core/serializerimpl.cpp b/src/core/serializerimpl.cpp new file mode 100644 index 0000000..cc239a1 --- /dev/null +++ b/src/core/serializerimpl.cpp @@ -0,0 +1,534 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// serializerimpl.cpp +#include "stdcore.h" +#include "serializerimpl.h" +#include "debug.h" +#include "archive.h" +#include "ntmbs.h" // for: eCharacterEncoding +#include "crc32.h" + +// static members +cSerializerImpl::SerMap cSerializerImpl::mSerCreateMap ; +cSerializerImpl::SerRefCountMap cSerializerImpl::mSerRefCountCreateMap ; + + +// RAD:09/01/99 -- No longer needed! +/////////////////////////////////////////////////////////////////////////////// +// util_TstrToStr -- converts the passed in tstring into a narrow string. maxSize +// indicates the size of the narrow buffer +/////////////////////////////////////////////////////////////////////////////// +// static inline void util_TstrToStr(char* pStr, const TCHAR* pTstr, int maxSize) +// { +// #ifdef _UNICODE +// ASSERT( maxSize >= wcstombs( 0, pTstr +// wcstombs(pStr, pTstr, maxSize); +// #else +// strncpy( pStr, pTstr, maxSize ); +// #endif +// } +// + + +/////////////////////////////////////////////////////////////////////////////// +// util_GetCrc -- calculates the crc for the narrow version of the type's AsString() +/////////////////////////////////////////////////////////////////////////////// +static uint32 util_GetCRC( const cType& type ) +{ + // + // convert this to narrow... + // + + // NOTE:RAD -- Fixed bug when going from TCHAR is Wide to Multibyte + // 09/01/99 - Increased performance by returning byte len instead of + // recalculating again in the call to crcUpdate. + // - Increased performance by removing superflous conversion + // when type.AsString() is already narrow. + // +#ifdef _UNICODE + + char sz[256]; + const uint8* pszType = (const uint8*)(&sz[0]); + const wchar_t* wsz = type.AsString(); + + ASSERT( countof(sz) >= ::wcstombs( 0, wsz, size_t(-1) ) ); + + int nBytes = (int)::wcstombs( (char*)pszType, wsz, countof(sz) ); + if ( nBytes == -1 ) // Bad character conversion! + { + throw eCharacterEncoding( + TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + +#else//!_UNICODE + + // We only need to count the characters + // RAD: Yeesh! This is already done for us in cType::mString!!! + const uint8* pszType = (const uint8*)( type.AsString() ); + int nBytes = ::strlen( (const char*)pszType ); + +#endif//_UNICODE + + ASSERT( sizeof(uint8) == sizeof(byte) ); + ASSERT( pszType && *pszType ); + + // + // calculate the crc... + // + CRC_INFO crc; + crcInit( crc ); + crcUpdate( crc, pszType, nBytes ); + crcFinit( crc ); + + return crc.crc; +} + +//############################################################################# +// class cSerializerImpl +//############################################################################# +cSerializerImpl::cSerializerImpl(cArchive& archive, Mode action, const TSTRING& fileName) : + mpArchive(&archive), + mMode(action), + mbInit(false), + mFileName( fileName ) +{ +} + +cSerializerImpl::~cSerializerImpl() +{ +} + +bool cSerializerImpl::IsWriting() const +{ + return (mMode == S_WRITE); +} + + +/////////////////////////////////////////////////////////////////////////////// +// static object registration functions; Exactly one of these should be called for +// every object that is to be serialized. +/////////////////////////////////////////////////////////////////////////////// + +// TODO:dmb - following line doesn't do anything??? +//std::allocator< std::pair< unsigned long, iTypedSerializable*(*)() > >; + +void cSerializerImpl::RegisterSerializable(const cType& type, iTypedSerializable::CreateFunc pFunc) +{ + uint32 crc = util_GetCRC( type ); + + if( cSerializerImpl::mSerCreateMap.find( crc ) != cSerializerImpl::mSerCreateMap.end() ) + { + // duplicate entry! + // + ASSERT( false ); + TOSTRINGSTREAM str; + str << _T("Duplicate entry in type table: ") << type.AsString() << std::endl; + throw eInternal(str.str()); + } + cSerializerImpl::mSerCreateMap[crc] = pFunc; +} + +void cSerializerImpl::RegisterSerializableRefCt(const cType& type, iSerRefCountObj::CreateFunc pFunc) +{ + uint32 crc = util_GetCRC( type ); + + if( cSerializerImpl::mSerRefCountCreateMap.find( crc ) != cSerializerImpl::mSerRefCountCreateMap.end() ) + { + // duplicate entry! + // + ASSERT( false ); + TOSTRINGSTREAM str; + str << _T("Duplicate entry in type table: ") << type.AsString() << std::ends; + throw eInternal(str.str()); + } + cSerializerImpl::mSerRefCountCreateMap[crc] = pFunc; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Init -- the job of init is to clear out the RefCountObj table, fill out the +// mTypeArray, and and write the header information +/////////////////////////////////////////////////////////////////////////////// +void cSerializerImpl::Init() +{ + cDebug d("cSerializerImpl::Init"); + d.TraceDetail("Entering; IsWriting = %s\n", IsWriting() ? "true" : "false"); + + mRefCtObjTbl.Clear(); + + mbInit = true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Finit +/////////////////////////////////////////////////////////////////////////////// +void cSerializerImpl::Finit() +{ + cDebug d("cSerializerImpl::Finit"); + d.TraceDetail("Exiting; IsWriting = %s\n", IsWriting() ? "true" : "false"); + mbInit = false; +} + +/////////////////////////////////////////////////////////////////////////////// +// WriteObjectDynCreate +/////////////////////////////////////////////////////////////////////////////// +void cSerializerImpl::WriteObjectDynCreate(const iTypedSerializable* pObj) +{ + ASSERT(mbInit); + ASSERT(IsWriting()); + cDebug d("cSerializerImpl::WriteObjectDynCreate"); + // CurrentPos() only works with bidir archive + //d.TraceDetail("Entering... Archive Offset = %d\n", mpArchive->CurrentPos()); + d.TraceDetail(_T(" Object Type = %s\n"), pObj->GetType().AsString()); + // first, we write out the header, which consists of the following: + // uint32 crc of the object's type + // int32 version of stored data + // int32 size of the chunk (counting from this point; not including the previous int32 + // int32 index into mRefCountObjTbl, or 0 if it isn't refrence counted. + // if the index already exists, then no data follows; a refrence + // should just be added to the existing object. + ASSERT(mpArchive != 0); + + // get the ident for this class type + // + uint32 crc = util_GetCRC( pObj->GetType() ); + + // + // make sure this type is registered, and figure out if it is refrence counted + // + SerRefCountMap::iterator i = mSerRefCountCreateMap.find( crc ); + bool bRefCount = true; + if( i == mSerRefCountCreateMap.end() ) + { + // + // maybe it is not refrence counted... + // + SerMap::iterator si = mSerCreateMap.find( crc ); + if( si == mSerCreateMap.end() ) + { + d.TraceError("Attempt to serialize unregistered type : %s\n", pObj->GetType().AsString()); + ThrowAndAssert(eSerializerUnknownType( pObj->GetType().AsString(), mFileName, eSerializer::TY_FILE )); + } + bRefCount = false; + } + + mpArchive->WriteInt32(crc); + mpArchive->WriteInt32(pObj->Version()); + // write a placeholder for the size; we will come back and fill in the right value later... + mpArchive->WriteInt32(0xffffffff); + + if(bRefCount) + { + // see if the object has already been serialized... + int idx; + if((idx = mRefCtObjTbl.Lookup(static_cast(pObj))) == 0) + { + // it is not in the table yet; add it and serialize the object + idx = mRefCtObjTbl.Add(static_cast(pObj)); + d.TraceDetail("Object [%d] written for first time...\n", idx); + mpArchive->WriteInt32(idx); + pObj->Write(this); + } + else + { + // since it is already in the table, just write the index number + d.TraceDetail("Object [%d] already serialized; incrementing refrence count.\n", idx); + mpArchive->WriteInt32(idx); + } + } + else + { + // not reference counted ... just write 0 + mpArchive->WriteInt32(0); + // ... then write the object. + pObj->Write(this); + + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadObjectDynCreate +/////////////////////////////////////////////////////////////////////////////// +iTypedSerializable* cSerializerImpl::ReadObjectDynCreate() +{ + cDebug d("cSerializerImpl::ReadObjectDynCreate"); + //d.TraceDetail("Entering... archive offset = %d\n", mpArchive->CurrentPos()); + + int32 size, objIdx; + uint32 crc; + // first, get the type... + mpArchive->ReadInt32(reinterpret_cast(crc)); + + // read in the version + int32 version; + mpArchive->ReadInt32(version); + + // read in the size and the index... + mpArchive->ReadInt32(size); + + // Save the position so we can seek correctly later on + //int64 sizePos = mpArchive->CurrentPos(); + + mpArchive->ReadInt32(objIdx); + if(objIdx == 0) + { + // the object is not reference counted; create and read in the object + // first, we need to create the object. + SerMap::iterator si; + si = mSerCreateMap.find(crc); + if(si == mSerCreateMap.end()) + { + // unable to find the creation function... + d.TraceError("Unable to find creation function for non-ref counted object %d\n", crc); + TOSTRINGSTREAM str; + #ifdef _DEBUG + // Let's only report the actual crc in debug mode + str << (int32)crc << std::ends; + #endif + ThrowAndAssert(eSerializerUnknownType(str.str(), mFileName, eSerializer::TY_FILE)); + } + iTypedSerializable* pObj = ((*si).second)(); + d.TraceDetail("Created non-ref counted object %s(%p)\n", pObj->GetType().AsString(), pObj); + pObj->Read(this, version); + + // seek past this object in case filepos is not correct! + //mpArchive->Seek(sizePos + size, cBidirArchive::BEGINNING); + + return pObj; + } + else + { + // refrence counted... + iSerRefCountObj* pObj; + pObj = mRefCtObjTbl.Lookup(objIdx); + if(pObj == NULL) + { + // not in table yet...first find the creation function + SerRefCountMap::iterator rci; + rci = mSerRefCountCreateMap.find(crc); + if(rci == mSerRefCountCreateMap.end()) + { + // unable to find the creation function... + d.TraceError("Unable to find creation function for ref counted object %d\n", crc); + TOSTRINGSTREAM str; + str << (int32)crc << std::ends; + ThrowAndAssert(eSerializerUnknownType(str.str(), mFileName, eSerializer::TY_FILE)); + } + pObj = ((*rci).second)(); + d.TraceDetail("Creating Ref-Coutnted object [%d] %s(%p)\n", objIdx, pObj->GetType().AsString(), pObj); + pObj->Read(this); + mRefCtObjTbl.Add(pObj, objIdx); + + // seek past this object in case filepos is not correct! + //mpArchive->Seek(sizePos + size, cBidirArchive::BEGINNING); + + return pObj; + } + else + { + // already serialized; just return this object. + d.TraceDetail("Adding refrence to previously serialized object [%d] %s(%p)\n", objIdx, pObj->GetType().AsString(), pObj); + pObj->AddRef(); + } + + // seek past this object in case filepos is not correct! + //mpArchive->Seek(sizePos + size, cBidirArchive::BEGINNING); + + return pObj; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// WriteObect, ReadObject +/////////////////////////////////////////////////////////////////////////////// +void cSerializerImpl::WriteObject(const iTypedSerializable* pObj) +{ + ASSERT(pObj != 0); + //ASSERT(mbInit); // this isn't needed if we are not writing the type array + ASSERT(IsWriting()); + cDebug d("cSerializerImpl::WriteObject"); + //d.TraceDetail("Entering... Archive Offset = %d\n", mpArchive->CurrentPos()); + d.TraceDetail(" Object Type = %s\n", pObj->GetType().AsString()); + // first, we write out the header, which consists of the following: + // int32 refrence into mTypeArray, indicating the object's type + // int32 version of stored data + // int32 size of the chunk (counting from this point; not including the previous int32 + // data the object data + ASSERT(mpArchive != 0); + + + // 5Nov 98 mdb -- I am removing the read and write of type info for this method; it is never used, since + // the object is already created when ReadObject() happens. The only good it might serve is in asserting that + // the input stream is valid, but I can do that with the 0xffffffff size below (asserting that it is the same + // when it is read back in) +/* int i = 0; + for(; i < mTypeArray.size(); i++) + { + if(pObj->GetType() == *mTypeArray[i]) + { + // aha! this is it! + break; + } + } + if(i == mTypeArray.size()) + { + // the type was not registered; + // a debate exists in my mind as to whether this should be an exception or an assertion -- mdb + d.TraceError("Attempt to serialize unregistered type : %s\n", pObj->GetType().AsString()); + ThrowAndAssert(eSerializerUnknownType(pObj->GetType().AsString())); + } + mpArchive->WriteInt32(i); +*/ + + mpArchive->WriteInt32(0); // place holder for type array index + mpArchive->WriteInt32(pObj->Version()); + // write a placeholder for the size; we will come back and fill in the right value later... + //int64 sizePos = mpArchive->CurrentPos(); + mpArchive->WriteInt32(0xffffffff); + + // write out the object! + pObj->Write(this); + + // finally, we need to go back and patch up the size... + //int64 returnPos = mpArchive->CurrentPos(); + //mpArchive->Seek(sizePos, cBidirArchive::BEGINNING); + //mpArchive->WriteInt32((int32)(returnPos - sizePos - sizeof(int32))); + //mpArchive->Seek(returnPos, cBidirArchive::BEGINNING); +} + +void cSerializerImpl::ReadObject(iTypedSerializable* pObj) +{ + cDebug d("cSerializerImpl::ReadObjectDynCreate"); + //d.TraceDetail("Entering... archive offset = %d\n", mpArchive->CurrentPos()); + + // NOTE -- type index stuff is gone; see the comment in WriteObject() + int32 /*typeIdx,*/ size; + // first, get the type... + /* + mpArchive->ReadInt32(typeIdx); + if((typeIdx < 0) || (typeIdx >= mTypeArray.size())) + { + // unknown type index! + d.TraceError("Encountered bad index into TypeArray: %d\n", typeIdx); + ThrowAndAssert(eSerializerInputStremTypeArray()); + } + const cType* pType = mTypeArray[typeIdx]; + */ + + // read in the version + int32 dummy, version; + mpArchive->ReadInt32(dummy); // old type array index + mpArchive->ReadInt32(version); + + // read in the size and the index... + mpArchive->ReadInt32(size); + + // use the size to assert that the file format is correct + if(size != (int)0xffffffff) + { + // unknown type index! + d.TraceError("Encountered bad size: %d\n", size); + ThrowAndAssert(eSerializerInputStremTypeArray(_T(""), mFileName, eSerializer::TY_FILE)); + } + + // remember current position + //int64 sizePos = mpArchive->CurrentPos(); + + // read in the object! + pObj->Read(this, version); + + // seek past this object in case filepos is not correct! + //mpArchive->Seek(sizePos + size, cBidirArchive::BEGINNING); +} + + +/////////////////////////////////////////////////////////////////////////////// +// archive wrapper +/////////////////////////////////////////////////////////////////////////////// +void cSerializerImpl::ReadInt16(int16& ret) +{ + mpArchive->ReadInt16(ret); +} + +void cSerializerImpl::ReadInt32(int32& ret) +{ + mpArchive->ReadInt32(ret); +} + +void cSerializerImpl::ReadInt64(int64& ret) +{ + mpArchive->ReadInt64(ret); +} + +void cSerializerImpl::ReadString(TSTRING& ret) +{ + mpArchive->ReadString(ret); +} + +int cSerializerImpl::ReadBlob(void* pBlob, int count) +{ + return mpArchive->ReadBlob(pBlob, count); +} + +void cSerializerImpl::WriteInt16(int16 i) +{ + mpArchive->WriteInt16(i); +} + +void cSerializerImpl::WriteInt32(int32 i) +{ + mpArchive->WriteInt32(i); +} + +void cSerializerImpl::WriteInt64(int64 i) +{ + mpArchive->WriteInt64(i); +} + +void cSerializerImpl::WriteString(const TSTRING& s) +{ + mpArchive->WriteString(s); +} + +void cSerializerImpl::WriteBlob(const void* pBlob, int count) +{ + mpArchive->WriteBlob(pBlob, count); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFileName +/////////////////////////////////////////////////////////////////////////////// +TSTRING cSerializerImpl::GetFileName() const +{ + return mFileName; +} + diff --git a/src/core/serializerimpl.h b/src/core/serializerimpl.h new file mode 100644 index 0000000..79b9284 --- /dev/null +++ b/src/core/serializerimpl.h @@ -0,0 +1,134 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializerimpl.h +// +// cSerializerImpl -- an implementation of the iSerializer interface + +#ifndef __SERIALIZERIMPL_H +#define __SERIALIZERIMPL_H + + +#ifndef __SERIALIZER_H +#include "serializer.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +#ifndef __SREFCOUNTOBJ_H +#include "srefcountobj.h" +#endif + +#ifndef __SREFCOUNTTBL_H +#include "srefcounttbl.h" +#endif + +class cArchive; + + +class cSerializerImpl : public iSerializer +{ +public: + enum Mode { S_READ, S_WRITE }; + cSerializerImpl (cArchive& archive, Mode action, const TSTRING& fileName = _T("") ); + // fileName is only used for error reporting purposes + virtual ~cSerializerImpl(); + + bool IsWriting() const; + + // Initializing and closing the archive + virtual void Init(); // throw eSerializer + // initializes the serializer; must be called before any reading or writing is done + virtual void Finit(); + // called after a session of serialization is done; called implicitely by the destructor + // if not called explicitely before destruction + + //Reading and writing objects Init() should have already been called or all these will fail. + virtual void WriteObjectDynCreate(const iTypedSerializable* pObj); // throw (eSerializer, eArchive) + // writes an object such that it can be dynamically created when read back in with + // ReadObject. + virtual iTypedSerializable* ReadObjectDynCreate(); // throw (eSerializer, eArchive); + // reads an object from the archive, returning a pointer to it. The caller is responsible for + // deleteing or Release()ing it when done. + virtual void WriteObject(const iTypedSerializable* pObj); // throw (eSerializer, eArchive) + // writes an object to the archive that will not be dynamically created + virtual void ReadObject(iTypedSerializable* pObj); // throw (eSerializer, eArchive) + // reads an object that was written with WriteObject() + + // members for registering classes to be serialized. One of these must be called exactly once + // for each class that is to be serialized. + static void RegisterSerializable (const cType& type, iTypedSerializable::CreateFunc pFunc); + static void RegisterSerializableRefCt (const cType& type, iSerRefCountObj::CreateFunc pFunc); + +// writing interface + // TODO -- I am not sure if I want to keep these or just have the serializer expose the archive. Actually, + // I think the best thing might be to have iSerializable only know about the archive + // Standard data read/write + // (All functions can throw eArchave exceptions). + virtual void ReadInt16(int16& ret); + virtual void ReadInt32(int32& ret); + virtual void ReadInt64(int64& ret); + virtual void ReadString(TSTRING& ret); + virtual int ReadBlob(void* pBlob, int count); + virtual void WriteInt16(int16 i); + virtual void WriteInt32(int32 i); + virtual void WriteInt64(int64 i); + virtual void WriteString(const TSTRING& s); + virtual void WriteBlob(const void* pBlob, int count); + + virtual TSTRING GetFileName() const; + +private: + cArchive* mpArchive; // the archive we are serializing to + Mode mMode; // are we writing or reading? + bool mbInit; // has init been called? + cSerRefCountTable mRefCtObjTbl; // keeps track of all ref counted objects that + // have been read or written during serialization + TSTRING mFileName; + + // creation function maps + typedef std::map SerMap; + typedef std::map SerRefCountMap; + static SerMap mSerCreateMap; + static SerRefCountMap mSerRefCountCreateMap; + + static void InitSerializableMaps(); + static void FinitSerializableMaps(); +}; + + + + +#endif + diff --git a/src/core/serializerimpl_t.cpp b/src/core/serializerimpl_t.cpp new file mode 100644 index 0000000..a2e9c33 --- /dev/null +++ b/src/core/serializerimpl_t.cpp @@ -0,0 +1,180 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializerimpl_t.cpp + +#include "stdcore.h" +#include "serializerimpl.h" +#include "serializable.h" +#include "types.h" +#include "archive.h" +#include "test/test.h" + +class cSerializerTestObject : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cSerializerTestObject(); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + bool CheckValid(); + +private: + int mNumber; + byte mData[20]; + TSTRING mString; +}; + +IMPLEMENT_TYPEDSERIALIZABLE(cSerializerTestObject, _T("cSerializerTestObject"), 0, 1) + +cSerializerTestObject::cSerializerTestObject() +{ + mNumber = 42; + memset(mData, 69, 20); + mString = _T("When the cows come home."); +} + +bool cSerializerTestObject::CheckValid() +{ + if (mNumber != 42) + return false; + + int i; + for (i=0; i<20; i++) + if (mData[i] != 69) + return false; + + if (mString.compare(_T("When the cows come home.")) != 0) + return false; + + return true; +} + +void cSerializerTestObject::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("cSerializerTestObject::Read()"))); + + // clear the object to test reading propperly + mNumber = 0; + memset(mData, 0, 20); + mString.erase(); + int32 number; + pSerializer->ReadInt32(number); + pSerializer->ReadBlob(mData, 20); + pSerializer->ReadString(mString); + mNumber = number; + +} + +void cSerializerTestObject::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(mNumber); + pSerializer->WriteBlob(mData, 20); + pSerializer->WriteString(mString); +} + +void TestSerializerImpl() +{ + cDebug db("TestSerializerImpl()"); + + db.TraceAlways("Entering...\n"); + + // Got to the regisiter the test class + cSerializerImpl::RegisterSerializable(CLASS_TYPE(cSerializerTestObject), cSerializerTestObject::Create); + + // writing + { + cFileArchive file; + file.OpenReadWrite(TEMP_DIR _T("/tmp.bin")); + cSerializerImpl serializer(file, cSerializerImpl::S_WRITE); + + serializer.Init(); + + cSerializerTestObject testobj; + testobj.Write(&serializer); + + db.TraceAlways(" Writeing object 1...\n"); + serializer.WriteObject(&testobj); + + db.TraceAlways(" Writeing object 2...\n"); + serializer.WriteObject(&testobj); + + db.TraceAlways(" Writeing object 3...\n"); + serializer.WriteObject(&testobj); + + db.TraceAlways(" Writeing object 4...\n"); + serializer.WriteObject(&testobj); + + serializer.Finit(); + } + + // reading + { + cFileArchive file; + file.OpenRead(TEMP_DIR _T("/tmp.bin")); + cSerializerImpl serializer(file, cSerializerImpl::S_READ); + + serializer.Init(); + + cSerializerTestObject testobj; + testobj.Read(&serializer); + TEST(testobj.CheckValid()); + + db.TraceAlways(" Reading and verifying object 1...\n"); + serializer.ReadObject(&testobj); + TEST(testobj.CheckValid()); + + db.TraceAlways(" Reading and verifying object 2...\n"); + serializer.ReadObject(&testobj); + TEST(testobj.CheckValid()); + + db.TraceAlways(" Reading and verifying object 3...\n"); + serializer.ReadObject(&testobj); + TEST(testobj.CheckValid()); + + db.TraceAlways(" Reading and verifying object 4...\n"); + serializer.ReadObject(&testobj); + TEST(testobj.CheckValid()); + + serializer.Finit(); + } + + db.TraceAlways("Done...\n"); + + return; +} + diff --git a/src/core/serializerutil.cpp b/src/core/serializerutil.cpp new file mode 100644 index 0000000..22368cb --- /dev/null +++ b/src/core/serializerutil.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// serilaizerutil.cpp +#include "stdcore.h" +#include "serializerutil.h" +#include "archive.h" +#include "serializer.h" + +namespace { +template +int64 CopyImpl(TO* pTo, FROM* pFrom, int64 amt) +{ + enum { BUF_SIZE = 8192 }; + int8 buf[BUF_SIZE]; + int64 amtLeft = amt; + + while(amtLeft > 0) + { + // NOTE: We use int's here rather than int64 because iSerializer and cArchive + // only take int's as their size parameter - dmb + int amtToRead = amtLeft > BUF_SIZE ? BUF_SIZE : (int)amtLeft; + int amtRead = pFrom->ReadBlob(buf, amtToRead ); + amtLeft -= amtRead; + pTo->WriteBlob(buf, amtRead); + if(amtRead < amtToRead) + break; + } + + // return the amount copied ... + return (amt - amtLeft); +} +} + + +int64 cSerializerUtil::Copy( iSerializer* pDest, cArchive* pSrc, int64 amt ) +{ + return CopyImpl( pDest, pSrc, amt ); +} + +int64 cSerializerUtil::Copy( cArchive* pDest, iSerializer* pSrc, int64 amt ) +{ + return CopyImpl( pDest, pSrc, amt ); +} + diff --git a/src/core/serializerutil.h b/src/core/serializerutil.h new file mode 100644 index 0000000..cb23dcc --- /dev/null +++ b/src/core/serializerutil.h @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serializerutil.h +// +#ifndef __SERIALIZERUTIL_H +#define __SERIALIZERUTIL_H +class cArchive; +class iSerializer; + +#ifndef __TYPES_H +#include "types.h" +#endif + +class cSerializerUtil +{ +public: + static int64 Copy( iSerializer* pDest, cArchive* pSrc, int64 amt ); // throw( eArchvie, eSerilaizer ) + static int64 Copy( cArchive* pDest, iSerializer* pSrc, int64 amt ); // throw( eArchvie, eSerilaizer ) + // these two methods copy data from archives to serializers and vice-versa. They + // throw exceptions on error; the return value is the amount that was copied. +}; + +#endif + diff --git a/src/core/serstring.cpp b/src/core/serstring.cpp new file mode 100644 index 0000000..84b8084 --- /dev/null +++ b/src/core/serstring.cpp @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serstring.cpp -- A serializable interface wrapper around a string +// +#include "stdcore.h" +#include "serstring.h" + +IMPLEMENT_TYPEDSERIALIZABLE(cSerializableNString, _T("cSerializableNString"), 0, 1) + +void cSerializableNString::Read (iSerializer* pSerializer, int32 version) +{ + int32 len; + pSerializer->ReadInt32(len); + mString.resize(len); + pSerializer->ReadBlob((void*)mString.data(), len); // note len is the bytelen of the data +} + +void cSerializableNString::Write(iSerializer* pSerializer) const +{ + int32 len = mString.length() * sizeof(char); + pSerializer->WriteInt32(len); + pSerializer->WriteBlob(mString.data(), len); +} + + +IMPLEMENT_TYPEDSERIALIZABLE(cSerializableWString, _T("cSerializableWString"), 0, 1) + +void cSerializableWString::Read (iSerializer* pSerializer, int32 version) +{ + int32 len; + pSerializer->ReadInt32(len); + mString.resize(len); + pSerializer->ReadBlob((void*)mString.data(), len); // note len is the bytelen of the data +} + +void cSerializableWString::Write(iSerializer* pSerializer) const +{ + int32 len = mString.length() * sizeof(wchar_t); + pSerializer->WriteInt32(len); + pSerializer->WriteBlob(mString.data(), len); +} + diff --git a/src/core/serstring.h b/src/core/serstring.h new file mode 100644 index 0000000..1aed650 --- /dev/null +++ b/src/core/serstring.h @@ -0,0 +1,88 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// serstring.h -- A serializable interface wrapper around a string +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SERSTRING_H +#define __SERSTRING_H + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +#ifndef __SERIALIZER_H +#include "serializer.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cSerializableNString + +class cSerializableNString : public iTypedSerializable +{ +public: + std::string mString; + + virtual ~cSerializableNString() {}; + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + DECLARE_TYPEDSERIALIZABLE() +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cSerializableWString + +class cSerializableWString : public iTypedSerializable +{ +public: + std::string mString; + + virtual ~cSerializableWString() {}; + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + DECLARE_TYPEDSERIALIZABLE() +}; + +#ifdef _UNICODE +typedef cSerializableWString cSerializableTSTRING; +#else +typedef cSerializableNString cSerializableTSTRING; +#endif + +#endif + diff --git a/src/core/sha.cpp b/src/core/sha.cpp new file mode 100644 index 0000000..91c6b59 --- /dev/null +++ b/src/core/sha.cpp @@ -0,0 +1,383 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//#ifndef lint +/*static char rcsid[] = "$Tripwire: sha.cpp,v 1.1 2000/10/28 01:15:20 itripn Exp $";*/ +//#endif + +/* + * sha.c + * + * signature function hook for SHA. + * + * Gene Kim + * Purdue University + * August 10, 1993 + */ + +/* --------------------------------- SHS.H ------------------------------- */ + +/* NIST proposed Secure Hash Standard. + + Written 2 September 1992, Peter C. Gutmann. + This implementation placed in the public domain. + + Comments to pgut1@cs.aukuni.ac.nz */ + + +/* --------------------------------- SHS.C ------------------------------- */ + +/* NIST proposed Secure Hash Standard. + + Written 2 September 1992, Peter C. Gutmann. + This implementation placed in the public domain. + + Comments to pgut1@cs.aukuni.ac.nz */ +#include "stdcore.h" +#include +#include +#include + +#include "sha.h" + +/* The SHS f()-functions */ + +#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* 32-bit rotate - kludged with shifts */ + +#define S(n,X) ( ( X << n ) | ( X >> ( 32 - n ) ) ) + +/* The initial expanding function */ + +#ifdef NEW_SHA +#define expand(count) temp = W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ];W[ count ] = S(1, temp) +#else +#define expand(count) W[ count ] = W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ] +#endif + +/* The four SHS sub-rounds */ + +#define subRound1(count) \ + { \ + temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound2(count) \ + { \ + temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound3(count) \ + { \ + temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound4(count) \ + { \ + temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +/* The two buffers of 5 32-bit words */ + +uint32 h0, h1, h2, h3, h4; +uint32 A, B, C, D, E; + +/* Initialize the SHS values */ + +void shsInit(SHS_INFO* shsInfo) +{ + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0L; + } + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers - it may be necessary to split it into + sections, eg based on the four subrounds */ + +void shsTransform(SHS_INFO *shsInfo) +{ + uint32 W[ 80 ], temp; + int i; + + /* Step A. Copy the data buffer into the local work buffer */ + for( i = 0; i < 16; i++ ) + W[ i ] = shsInfo->data[ i ]; + + /* Step B. Expand the 16 words into 64 temporary data words */ + expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 ); + expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 ); + expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 ); + expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 ); + expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 ); + expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 ); + expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 ); + expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 ); + expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 ); + expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 ); + expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 ); + expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 ); + expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 ); + + /* Step C. Set up first buffer */ + A = shsInfo->digest[ 0 ]; + B = shsInfo->digest[ 1 ]; + C = shsInfo->digest[ 2 ]; + D = shsInfo->digest[ 3 ]; + E = shsInfo->digest[ 4 ]; + + /* Step D. Serious mangling, divided into four sub-rounds */ + subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 ); + subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 ); + subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 ); + subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 ); + subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 ); + subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 ); + subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 ); + subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 ); + subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 ); + subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 ); + subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 ); + subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 ); + subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 ); + subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 ); + subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 ); + subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 ); + subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 ); + subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 ); + subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 ); + subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 ); + + /* Step E. Build message digest */ + shsInfo->digest[ 0 ] += A; + shsInfo->digest[ 1 ] += B; + shsInfo->digest[ 2 ] += C; + shsInfo->digest[ 3 ] += D; + shsInfo->digest[ 4 ] += E; + } + +#ifndef WORDS_BIGENDIAN + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independant by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +static void byteReverse(uint32* buffer, int byteCount) + { + uint32 value; + int count; + + byteCount /= sizeof( uint32 ); + for( count = 0; count < byteCount; count++ ) + { + value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 ); + buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 ); + } + } +#endif /* #ifndef WORDS_BIGENDIAN */ + +/* Update SHS for a block of data. This code assumes that the buffer size + is a multiple of SHS_BLOCKSIZE bytes long, which makes the code a lot + more efficient since it does away with the need to handle partial blocks + between calls to shsUpdate() */ + +void shsUpdate(SHS_INFO* shsInfo, uint8* buffer, int count) + { + /* Update bitcount */ + if( ( shsInfo->countLo + ( ( uint32 ) count << 3 ) ) < shsInfo->countLo ) + shsInfo->countHi++; /* Carry from low to high bitCount */ + shsInfo->countLo += ( ( uint32 ) count << 3 ); + shsInfo->countHi += ( ( uint32 ) count >> 29 ); + + /* Process data in SHS_BLOCKSIZE chunks */ + while( count >= SHS_BLOCKSIZE ) + { + memcpy( (char *) shsInfo->data, (char *) buffer, SHS_BLOCKSIZE ); +#ifndef WORDS_BIGENDIAN + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); +#endif /* #ifndef WORDS_BIGENDIAN */ + shsTransform( shsInfo ); + buffer += SHS_BLOCKSIZE; + count -= SHS_BLOCKSIZE; + } + + /* Handle any remaining bytes of data. This should only happen once + on the final lot of data */ + memcpy( (char *) shsInfo->data, (char *) buffer, count ); + } + +void shsFinal(SHS_INFO *shsInfo) +{ + int count; + uint32 lowBitcount = shsInfo->countLo, highBitcount = shsInfo->countHi; + + /* Compute number of bytes mod 64 */ + count = ( int ) ( ( shsInfo->countLo >> 3 ) & 0x3F ); + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + ( ( uint8 * ) shsInfo->data )[ count++ ] = 0x80; + + /* Pad out to 56 mod 64 */ + if( count > 56 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( ( char * ) shsInfo->data + count, 0, 64 - count ); +#ifndef WORDS_BIGENDIAN + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); +#endif /* #ifndef WORDS_BIGENDIAN */ + shsTransform( shsInfo ); + + /* Now fill the next block with 56 bytes */ + memset( (char *) shsInfo->data, 0, 56 ); + } + else + /* Pad block to 56 bytes */ + memset( ( char * ) shsInfo->data + count, 0, 56 - count ); +#ifndef WORDS_BIGENDIAN + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); +#endif /* #ifndef WORDS_BIGENDIAN */ + + /* Append length in bits and transform */ + shsInfo->data[ 14 ] = highBitcount; + shsInfo->data[ 15 ] = lowBitcount; + + shsTransform( shsInfo ); +#ifndef WORDS_BIGENDIAN + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); +#endif /* #ifndef WORDS_BIGENDIAN */ + } + +#ifdef TEST + +/* ----------------------------- SHS Test code --------------------------- */ + +/* Size of buffer for SHS speed test data */ + +#define TEST_BLOCK_SIZE ( SHS_DIGESTSIZE * 100 ) + +/* Number of bytes of test data to process */ + +#define TEST_BYTES 10000000L +#define TEST_BLOCKS ( TEST_BYTES / TEST_BLOCK_SIZE ) + +void main() + { + SHS_INFO shsInfo; + time_t endTime, startTime; + uint8 data[ TEST_BLOCK_SIZE ]; + long i; + + /* Test output data (this is the only test data given in the SHS + document, but chances are if it works for this it'll work for + anything) */ + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( uint8 * ) "abc", 3 ); + shsFinal( &shsInfo ); + if( shsInfo.digest[ 0 ] != 0x0164B8A9L || + shsInfo.digest[ 1 ] != 0x14CD2A5EL || + shsInfo.digest[ 2 ] != 0x74C4F7FFL || + shsInfo.digest[ 3 ] != 0x082C4D97L || + shsInfo.digest[ 4 ] != 0xF1EDF880L ) + { + puts( "Error in SHS implementation" ); + exit( -1 ); + } + + /* Now perform time trial, generating MD for 10MB of data. First, + initialize the test data */ + memset( data, 0, TEST_BLOCK_SIZE ); + + /* Get start time */ + printf( "SHS time trial. Processing %ld characters...\n", TEST_BYTES ); + time( &startTime ); + + /* Calculate SHS message digest in TEST_BLOCK_SIZE byte blocks */ + shsInit( &shsInfo ); + for( i = TEST_BLOCKS; i > 0; i-- ) + shsUpdate( &shsInfo, data, TEST_BLOCK_SIZE ); + shsFinal( &shsInfo ); + + /* Get finish time and time difference */ + time( &endTime ); + printf( "Seconds to process test input: %ld\n", endTime - startTime ); + printf( "Characters processed per second: %ld\n", TEST_BYTES / ( endTime - startTime ) ); + } + +#endif + diff --git a/src/core/sha.h b/src/core/sha.h new file mode 100644 index 0000000..0a496e9 --- /dev/null +++ b/src/core/sha.h @@ -0,0 +1,88 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* Useful defines/typedefs */ + +#ifndef __SHA_H +#define __SHA_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_BLOCKSIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + uint32 digest[ 5 ]; /* Message digest */ + uint32 countLo, countHi; /* 64-bit bit count */ + uint32 data[ 16 ]; /* SHS data buffer */ + } SHS_INFO; + +/* Whether the machine is little-endian or not */ + +//int sig_sha_get(); +void shsInit(SHS_INFO *shsInfo); +void shsUpdate(SHS_INFO* shsInfo, uint8* buffer, int count); +void shsFinal(SHS_INFO* shsInfo); + +/* The next def turns on the change to the algorithm introduced by NIST at + * the behest of the NSA. It supposedly corrects a weakness in the original + * formulation. Bruce Schneier described it thus in a posting to the + * Cypherpunks mailing list on June 21, 1994 (as told to us by Steve Bellovin): + * + * This is the fix to the Secure Hash Standard, NIST FIPS PUB 180: + * + * In Section 7 of FIPS 180 (page 9), the line which reads + * + * "b) For t=16 to 79 let Wt = Wt-3 XOR Wt-8 XOR Wt-14 XOR + * Wt-16." + * + * is to be replaced by + * + * "b) For t=16 to 79 let Wt = S1(Wt-3 XOR Wt-8 XOR Wt-14 XOR + * Wt-16)." + * + * where S1 is a left circular shift by one bit as defined in + * Section 3 of FIPS 180 (page 6): + * + * S1(X) = (X<<1) OR (X>>31). + * + */ + +#define NEW_SHA + +#endif //__SHA_H + diff --git a/src/core/srefcountobj.cpp b/src/core/srefcountobj.cpp new file mode 100644 index 0000000..da2a5c2 --- /dev/null +++ b/src/core/srefcountobj.cpp @@ -0,0 +1,45 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// srefcountobj.cpp +/////////////////////////////////////////////////////////////////////////////// +#include "stdcore.h" +#include "srefcountobj.h" + +/////////////////////////////////////////////////////////////////////////////// +// class cSerializableRefCountObj +// + +iSerRefCountObj::~iSerRefCountObj() +{ +} + diff --git a/src/core/srefcountobj.h b/src/core/srefcountobj.h new file mode 100644 index 0000000..5098687 --- /dev/null +++ b/src/core/srefcountobj.h @@ -0,0 +1,86 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// srefcountobj.h +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SREFCOUNTOBJ_H +#define __SREFCOUNTOBJ_H + +#ifndef __REFCOUNTOBJ_H +#include "refcountobj.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cSerializableRefCountObj +// +class iSerRefCountObj : public cRefCountObj, public iTypedSerializable +{ +public: + // the creation function + typedef iSerRefCountObj* (*CreateFunc)(void); + +protected: + virtual ~iSerRefCountObj(); + +}; + +////////////////////////////// +// convenience macros +#define DECLARE_SERREFCOUNT() \ + DECLARE_TYPED() \ +public: \ + static iSerRefCountObj* Create(); \ + virtual int32 Version() const; + +#define IMPLEMENT_SERREFCOUNT(CLASS, TYPEDSTRING, VERSION_MAJOR, VERSION_MINOR) \ + IMPLEMENT_TYPED(CLASS, TYPEDSTRING) \ + iSerRefCountObj* CLASS::Create() \ + { \ + return new CLASS; \ + } \ + int32 CLASS::Version() const \ + { \ + return iTypedSerializable::MkVersion(VERSION_MAJOR, VERSION_MINOR); \ + } + + +#endif + diff --git a/src/core/srefcountobj_t.cpp b/src/core/srefcountobj_t.cpp new file mode 100644 index 0000000..9136c5d --- /dev/null +++ b/src/core/srefcountobj_t.cpp @@ -0,0 +1,145 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// srefcountobj_t.cpp +/////////////////////////////////////////////////////////////////////////////// + +#include "stdcore.h" +#include "serializerimpl.h" + +#include "errorgeneral.h" +#include "debug.h" +#include "archive.h" +#include "srefcountobj.h" + +class cSerRefCountObjTest : public iSerRefCountObj +{ + DECLARE_SERREFCOUNT() + +public: + cSerRefCountObjTest(); + +protected: + ~cSerRefCountObjTest(); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +private: + int mDummyData; + +}; + +IMPLEMENT_SERREFCOUNT(cSerRefCountObjTest, _T("cSerRefCountObjTest"), 0, 1); + +cSerRefCountObjTest::cSerRefCountObjTest() +{ + static int counter; + mDummyData = ++counter; +} + +cSerRefCountObjTest::~cSerRefCountObjTest() +{ +} + + +void cSerRefCountObjTest::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("cSerRefCountObjTest::Read()"))); + + int32 dummy; + pSerializer->ReadInt32(dummy); + mDummyData = dummy; +} + +void cSerRefCountObjTest::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(mDummyData); +} + + + +//////////////////////////////////////////////////////////////////////////////// + +void TestSerRefCountObj() +{ + // first, we need to register the object with the serializer class... + cSerializerImpl::RegisterSerializableRefCt(CLASS_TYPE(cSerRefCountObjTest), cSerRefCountObjTest::Create); + + cSerRefCountObjTest* pObj1 = new cSerRefCountObjTest; + cSerRefCountObjTest* pObj2 = new cSerRefCountObjTest; + pObj1->AddRef(); + cSerRefCountObjTest* pObj3 = pObj1; + pObj1->AddRef(); + cSerRefCountObjTest* pObj4 = pObj1; + + cMemoryArchive memarchive; + { + cSerializerImpl serializer(memarchive, cSerializerImpl::S_WRITE); + serializer.Init(); + serializer.WriteObjectDynCreate(pObj1); + serializer.WriteObjectDynCreate(pObj2); + serializer.WriteObjectDynCreate(pObj3); + serializer.WriteObjectDynCreate(pObj4); + serializer.Finit(); + } + + pObj1->Release(); + pObj2->Release(); + pObj3->Release(); + pObj4->Release(); + + { + memarchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl serializer(memarchive, cSerializerImpl::S_READ); + serializer.Init(); + pObj1 = static_cast(serializer.ReadObjectDynCreate()); + pObj2 = static_cast(serializer.ReadObjectDynCreate()); + pObj3 = static_cast(serializer.ReadObjectDynCreate()); + pObj4 = static_cast(serializer.ReadObjectDynCreate()); + serializer.Finit(); + } + + ASSERT(pObj1 == pObj3); + ASSERT(pObj1 == pObj4); + ASSERT(pObj1 != pObj2); + + pObj1->Release(); + pObj2->Release(); + pObj3->Release(); + pObj4->Release(); + + return; +} + diff --git a/src/core/srefcounttbl.cpp b/src/core/srefcounttbl.cpp new file mode 100644 index 0000000..ceffb19 --- /dev/null +++ b/src/core/srefcounttbl.cpp @@ -0,0 +1,157 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// srefcounttbl.cpp +/////////////////////////////////////////////////////////////////////////////// +#include "stdcore.h" +#include "srefcounttbl.h" +#include "debug.h" +#include "errorgeneral.h" +#include "error.h" +#include "errorutil.h" + + +/////////////////////////////////////////////////////////////////////////////// +// class cSerRefCountTable +/////////////////////////////////////////////////////////////////////////////// + +cSerRefCountTable::cSerRefCountTable() +{ +} + +cSerRefCountTable::~cSerRefCountTable() +{ +} + +void cSerRefCountTable::Clear() +{ + mIDToObjTbl.clear(); + mObjToIdTbl.clear(); +} + +// find the table id for object. returns 0 if not in table. +int cSerRefCountTable::Lookup(const iSerRefCountObj* pObj) +{ + std::map::iterator itr; + + // pay no attention to this cast :-) + itr = mObjToIdTbl.find(const_cast(pObj)); + + return itr == mObjToIdTbl.end() ? NULL : itr->second; +} + +// find object for specified id. returns NULL if not in table +iSerRefCountObj* cSerRefCountTable::Lookup(int id) +{ + std::map::iterator itr; + + itr = mIDToObjTbl.find(id); + + return itr == mIDToObjTbl.end() ? NULL : itr->second; +} + +// Add an object to the table, optionally specifying an ID. Returns a +// unique ID for the object. ASSERTs and throws exception if object is +// already in table or the ID is already taken. +int cSerRefCountTable::Add(iSerRefCountObj* pObj, int id) +{ + if (Lookup(pObj) != 0) + { + // this should be a programming error, but we will throw just to be safe... + ThrowAndAssert(eInternal(_T("cSerRefCountTable::Add() passed object already in table."))); + } + if (id == 0) + { + id = mIDToObjTbl.empty() ? 1 : mIDToObjTbl.rbegin()->first + 1; + ASSERT(Lookup(id) == NULL); + } + else if (Lookup(id) != NULL) + { + // this should be a programming error, but we will throw just to be safe... + ThrowAndAssert(eInternal(_T("cSerRefCountTable::Add() passed ID already in table."))); + } + + mIDToObjTbl.insert( MapIDTObj::value_type(id, pObj)); + mObjToIdTbl.insert( MapObjIDT::value_type(pObj, id)); + + return id; +} + +int cSerRefCountTable::Add(const iSerRefCountObj* pObj, int id) +{ + iSerRefCountObj* pNonConst = const_cast(pObj); + return Add(pNonConst, id); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cSerRefCountTableMap +/////////////////////////////////////////////////////////////////////////////// +/* +// creates a new cSerRefCountTable +void cSerRefCountTableMap::AddSerializer(const cSerializer* pSerializer) +{ + #ifdef _DEBUG + // make sure we don't have this serialzier in here yet + { + std::map::iterator itr; + itr = mMap.find(pSerializer); + ASSERT(itr == mMap.end()); + } + #endif + + std::pair new_value(pSerializer, new cSerRefCountTable); + + mMap.insert(mMap.end(), new_value); +} + +// removes table for specified serializer +void cSerRefCountTableMap::RemoveSerializer(const cSerializer* pSerializer) +{ + std::map::iterator itr; + itr = mMap.find(pSerializer); + ASSERT(itr != mMap.end()); + + delete itr->second; + mMap.erase(itr); +} + +// removes all contained cSerRefCountTable's +cSerRefCountTableMap::~cSerRefCountTableMap() +{ + while (!mMap.empty()) + { + delete mMap.begin()->second; + mMap.erase(mMap.begin()); + } +} +*/ + diff --git a/src/core/srefcounttbl.h b/src/core/srefcounttbl.h new file mode 100644 index 0000000..35b9e39 --- /dev/null +++ b/src/core/srefcounttbl.h @@ -0,0 +1,92 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// srefcounttbl.h +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SREFCOUNTTBL_H +#define __SREFCOUNTTBL_H + +class iSerRefCountObj; +class iSerializer; + +class cSerRefCountTable +{ +public: + cSerRefCountTable(); + virtual ~cSerRefCountTable(); + + // find the table id for object. returns 0 if not in table. + int Lookup(const iSerRefCountObj* pObj); + + // find object for specified id. returns NULL if not in table + iSerRefCountObj* Lookup(int id); + + // Add an object to the table, optionally specifying an ID. Returns a + // unique ID for the object. ASSERTs and throws exception if object is + // already in table or the ID is already taken. + int Add( iSerRefCountObj* pObj, int id = 0); + int Add(const iSerRefCountObj* pObj, int id = 0); + // TODO -- Note that this class is not really const-correct in that the const version of + // Add() just casts away the constness. The right thing to do is to make the serializer + // use different versions of this class (const and non-const) depending on whether it is + // reading or writing and (maybe?) make this class a template class so that it can map + // to either const or non-const objects. + + + // clears out the table + void Clear(); + +protected: + typedef std::map MapIDTObj; + typedef std::map MapObjIDT; + + MapIDTObj mIDToObjTbl; + MapObjIDT mObjToIdTbl; +}; + +// not used any more, so commented out -- mdb +/* +class cSerRefCountTableMap +{ +public: + std::map mMap; + + void AddSerializer(const iSerializer* pSerializer); + // creates a new cSerRefCountTable + void RemoveSerializer(const iSerializer* pSerializer); // removes table for specified serializer + + ~cSerRefCountTableMap(); // removes all contained cSerRefCountTable's +}; +*/ +#endif + diff --git a/src/core/stdcore.cpp b/src/core/stdcore.cpp new file mode 100644 index 0000000..1798c5b --- /dev/null +++ b/src/core/stdcore.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdcore.cpp +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// + +#include "stdcore.h" + +// eof: stdcore.cpp diff --git a/src/core/stdcore.h b/src/core/stdcore.h new file mode 100644 index 0000000..fc5848b --- /dev/null +++ b/src/core/stdcore.h @@ -0,0 +1,127 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdcore.h +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// +// Standard includes for core, and therefore the entire project +// + +#ifndef __STDCORE_H +#define __STDCORE_H + + +//--Include Core Platform Declarations + +#include "platform.h" + +//--Disable some level 4 warnings + +#if IS_MSVC + + #define NOMINMAX //--Disable min/max macros + + #include // ARGH!! This resumes certain warnings! + + #pragma warning( disable: 4786 ) // Token Name > 255 + #pragma warning( disable: 4127 ) // constant expression (e.g. ASSERT) + #pragma warning( disable: 4291 ) // Incorrectly called when new(nothrow)!!! + #pragma warning( disable: 4097 ) // Type synonyms are good! + #pragma warning( disable: 4511 ) // Can't create copy ctor! (e.g.Private CTOR) + #pragma warning( disable: 4512 ) // Can't create assignment!(e.g.Private CTOR) + #pragma warning( disable: 4100 ) // Formal argument not used + #pragma warning( disable: 4710 ) // Compiler did not inline function + +#ifndef _DEBUG // ASSERT's are disabled give a lot of these + #pragma warning( disable: 4702 ) // ---Unreachable Code +#endif + + /* NOTE:RAD:05/09/1999 -- Plaguers STDCPP implementation is SOOO bad + it creates all these errors when compiling at W4. By doing a push + before disabling them, we can still generate them for ourselves + without a lot of noise. The warnings before this push, we want to + always disable. */ + + #pragma warning( push ) + + #pragma warning( disable: 4663 ) // Old template specialization syntax + #pragma warning( disable: 4018 ) // Signed unsigned mismatch + #pragma warning( disable: 4245 ) // Signed unsigned mismatch + #pragma warning( disable: 4663 ) // Use new template specialization syntax: template<> + #pragma warning( disable: 4701 ) // local variable 'X' may be used without having been initialized + #pragma warning( disable: 4510 ) // 'X' : default constructor could not be generated + #pragma warning( disable: 4610 ) // struct 'X' can never be instantiated - user defined constructor required + #pragma warning( disable: 4146 ) // unary minus operator applied to unsigned type, result still unsigned + #pragma warning( disable: 4244 ) // '=' : conversion from 'unsigned int' to 'char', possible loss of data + #pragma warning( disable: 4511 ) + #pragma warning( disable: 4503 ) + +#endif // #if IS_MSVC + + +//--Include Standard CPP Declarations + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if IS_MSVC + #pragma warning( pop ) // Resume W4 msgs for TSS code +#endif + +//--Include Platform Specific Declarations + + + +//--Include Common Core Declarations + +#include "./tchar.h" +#include "./types.h" +#include "./error.h" +#include "./debug.h" + + +#endif//__STDCORE_H + diff --git a/src/core/stringutil.cpp b/src/core/stringutil.cpp new file mode 100644 index 0000000..5d8a0c5 --- /dev/null +++ b/src/core/stringutil.cpp @@ -0,0 +1,512 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: stringutil.cpp +* Date....: 09/02/99 +* Creator.: +* +* This module implements the cStringUtil class and helpers. This class, +* primarily, is used to convert between various character formats. The +* supported formats include: +* +* NTWCS - using 32-bit wchar_t +* NTWCS - using 16-bit wchar_t +* NTMBS - using integral char's +* +* PLEASE NOTE: +* Refrain from using the StrToTStr, TStrToStr, WStrToTStr, and +* etc calls and instead use the type dispatched member: +* +* DestT::const_iterator Convert( DestT&, const SrcT& ); +* +* It can be used like so: +* +* TSTRING tstr; +* TCOUT << cStringUtil::Convert( tstr, sUnknownType ); +* +* This call makes our code more portable and extensible by not embedding +* type selection in the names of interfaces. For example: +* +* std::string s1 = cStringUtil::TStrToStr( TSTRING( "Huh" ) ); +* +* Can be rewritten as: +* +* std::string s1; +* cStringUtil::Convert( s1, TSTRING( "Huh" ) ); +*/ + +/// Requirements + +#include "stdcore.h" // for: pch + +#include "stringutil.h" // for: These Declarations +#include "debug.h" // for: Debugging Interface +#include "codeconvert.h" // for: iconv abstractions +#include "ntmbs.h" // for: eCharacterEncoding +#include "hashtable.h" + + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// String Cache +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// TODO:BAM -- use these for mb -> UCS2 conversions as well? + +class tss_hash_key_convert +{ +public: + const byte* operator()( const wc16_string& s, int* const pcbKeyLen ) + { + *pcbKeyLen = sizeof(WCHAR16) * s.length(); + return (byte*)s.c_str(); + } +}; + +class tss_hash_key_compare +{ +public: + bool operator()( const wc16_string& lhs, const wc16_string& rhs ) + { + return ( lhs.compare( rhs ) == 0 ); + } +}; + +namespace /* Module Local */ +{ + typedef + cHashTable< wc16_string, + TSTRING, + tss_hash_key_compare, + tss_hash_key_convert > + hashtable_t; + + hashtable_t& tss_GetHashTable() + { + static hashtable_t s_table; + return s_table; + } +}//Anon. + + +inline void tss_insert_in_hash( const wc16_string& lhs, const TSTRING& rhs ) +{ + tss_GetHashTable().Insert( lhs, rhs ); +} + +inline bool tss_find_in_hash( const wc16_string& lhs, TSTRING& rhs ) +{ + return( tss_GetHashTable().Lookup( lhs, rhs ) ); +} + +#ifdef _UNICODE + +inline bool tss_find_in_hash( const wc16_string& lhs, std::string& rhs ) +{ + return false; // don't have a hash table for this! +} + +inline void tss_insert_in_hash( const wc16_string& lhs, const std::string& rhs ) +{ + return; // don't have a hash table for this! +} + +#endif + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Type Dispatched Conversions +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/*static*/ +std::string::const_iterator +cStringUtil::Convert( std::string& nbs, const wc16_string& dbs ) +{ + cDebug d("cStringUtil::Convert( char, w16 )"); + + ASSERT( (void*)nbs.c_str() != (void*)dbs.c_str() ); + + if ( dbs.empty() ) + nbs.erase(); + else + { + if( tss_find_in_hash( dbs, nbs ) ) + { + d.TraceNever( _T("found string in hash table\n") ); + return nbs.begin(); + } + else + { + d.TraceNever( _T("didn't find string in hash table\n") ); + } + + /* + d.TraceDebug( _T("converting: \n") ); + for( int i = 0; i < dbs.size(); i++ ) + d.TraceDebug( _T("0x%04X\n"), dbs[i] ); + d.TraceDebug( _T("----\n") ); + */ + + nbs.resize( dbs.size() * MB_CUR_MAX ); + + int nWrote = + iCodeConverter::GetInstance()->Convert( + (char*)nbs.c_str(), nbs.size(), + dbs.c_str(), dbs.size() ); // c_str() because must be null terminated + + d.TraceDetail( _T("iCodeConverter returned %d\n"), nWrote ); + + if ( nWrote == -1 ) + throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + + nbs.resize( nWrote ); + + tss_insert_in_hash( dbs, nbs ); + } + + + return nbs.begin(); +} + +/*static*/ +wc16_string::const_iterator +cStringUtil::Convert( wc16_string& dbs, const std::string& nbs ) +{ + cDebug d("cStringUtil::Convert( w16, char )"); + + if (nbs.size() != 0) + { + dbs.resize( nbs.size() ); + + // d.TraceDebug( "converting <%s>\n", nbs.c_str() ); + + int nWrote = + iCodeConverter::GetInstance()->Convert( + (WCHAR16*)dbs.c_str(), dbs.length(), + nbs.c_str(), nbs.size() ); // c_str() because must be null terminated + + d.TraceDetail( _T("iCodeConverter returned %d\n"), nWrote ); + + if ( nWrote == -1 ) + { + throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + } + + dbs.resize( nWrote ); + + /* + d.TraceDebug( _T("converted to: \n") ); + for( int i = 0; i < dbs.size(); i++ ) + d.TraceDebug( _T("0x%04X\n"), dbs[i] ); + d.TraceDebug( _T("----\n") ); + */ + } + else + dbs.resize(0); + + return dbs.begin(); +} + +#if SUPPORTS_WCHART && WCHAR_REP_IS_UCS2 + +/*static*/ +std::wstring::const_iterator +cStringUtil::Convert( std::wstring& wcs, const wc16_string& dbs ) +{ + if (dbs.size() != 0) + { + if( tss_find_in_hash( dbs, wcs ) ) + return wcs.begin(); + + wcs.resize( dbs.size() ); + std::copy( dbs.begin(), dbs.end(), wcs.begin() ); + + tss_insert_in_hash( dbs, wcs ); + } + else + wcs.erase(); + + return wcs.begin(); +} + +/*static*/ +wc16_string::const_iterator +cStringUtil::Convert( wc16_string& dbs, const std::wstring& wcs ) +{ + if (wcs.size() != 0) + { + dbs.resize( wcs.size() ); + std::copy( wcs.begin(), wcs.end(), dbs.begin() ); + } + else + dbs.resize(0); + + return dbs.begin(); +} + +/*static*/ +std::wstring::const_iterator +cStringUtil::Convert( std::wstring& wcs, const std::string& nbs ) +{ + if (nbs.size() != 0) + { + wcs.resize( nbs.size() ); + + size_t nWrote = ::mbstowcs( (wchar_t*)wcs.c_str(), nbs.c_str(), wcs.size() + 1 ); + if ( nWrote == (size_t)-1 ) + throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + + wcs.resize( nWrote ); + } + else + wcs.erase(); + + return wcs.begin(); +} + +/*static*/ +std::string::const_iterator +cStringUtil::Convert( std::string& nbs, const std::wstring& wcs ) +{ + if (wcs.size() != 0) + { + if( tss_find_in_hash( wc16_string( wcs.c_str() ), nbs ) ) + return nbs.begin(); + + nbs.resize( MB_CUR_MAX * wcs.size() ); + size_t nWrote = ::wcstombs( (char*)nbs.c_str(), wcs.c_str(), nbs.size() + 1 ); + if ( nWrote == (size_t)-1 ) + throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + + nbs.resize( nWrote ); + + tss_insert_in_hash( wc16_string( wcs.c_str() ), nbs ); + } + else + nbs.erase(); + + return nbs.begin(); +} + +#endif // SUPPORTS_WCHART && WCHAR_REP_IS_UCS2 + + +/// TSTRING and Type Knowledge Required + +/////////////////////////////////////////////////////////////////////////////// +// TstrToStr +/////////////////////////////////////////////////////////////////////////////// + +std::string +cStringUtil::TstrToStr( const TSTRING& tstr ) +{ + std::string s; + cStringUtil::Convert( s, tstr ); + return s; +} + +/////////////////////////////////////////////////////////////////////////////// +// StrToTstr +/////////////////////////////////////////////////////////////////////////////// +TSTRING cStringUtil::StrToTstr( const std::string& rhs ) +{ + TSTRING lhs; + cStringUtil::Convert( lhs, rhs ); + return lhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// WstrToTstr +/////////////////////////////////////////////////////////////////////////////// +TSTRING cStringUtil::WstrToTstr(const wc16_string& rhs ) +{ + TSTRING lhs; + cStringUtil::Convert( lhs, rhs ); + return lhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// TstrToWstr +/////////////////////////////////////////////////////////////////////////////// +wc16_string cStringUtil::TstrToWstr( const TSTRING& rhs ) +{ + wc16_string lhs; + cStringUtil::Convert( lhs, rhs ); + return lhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// StringIsInteger -- returns true if the string is a length of at least one +// and contains nothing other than [0-9]. +// Used to verify a string is acceptable to pass to atoi() +/////////////////////////////////////////////////////////////////////////////// +#ifdef OLDCODE +bool cStringUtil::StringIsInteger(TCHAR* pStr) +{ + int len = _tcslen(pStr); + + if (len <= 0) + return false; + + for (int i = 0; i < len; ++i) + { + if (pStr[i] < _T('0') || pStr[i] > _T('9')) + return false; + } + + return true; +} +#endif//OLDCODE + +// eof: stringutil.cpp + +/* + + +typedef wchar_t dbchar_t; +typedef char mbchar_t; + +class cMBUCS2Cache +{ +public: + cMBUCS2Cache(); + ~cMBUCS2Cache(); + + bool Convert(dbchar_t& ret, mbchar_t* pMBChar); + // returns false if conversion could not be done + void Add(mbchar_t* pMBchar, int mblen); + // add a mb char def to the chache + +protected: + struct Element + { + union + { + Element* mpNext; // points to another Element[256] + dbchar_t mUCS2; + }; + + enum ElementDefinition { UNDEFINED, UCS2, CONTINUES }; + short mElementDefinition; + + Element() { mElementDefinition = UNDEFINED; } + ~Element() { if (mElementDefinition == CONTINUES) delete mpNext; } + }; + + Element mTop[256]; +}; + + +cMBUCS2Cache::cMBUCS2Cache() +{ +} + +cMBUCS2Cache::~cMBUCS2Cache() +{ +} + +// returns false if conversion could not be done +bool cMBUCS2Cache::Convert(dbchar_t& ret, mbchar_t* pMBChar) +{ + Element* pNode = mTop; + while (pNode[*pMBChar].mElementDefinition == Element::CONTINUES) + { + pNode = pNode[*pMBChar].mpNext; + ++pMBChar; + } + + if (pNode[*pMBChar].mElementDefinition == Element::UCS2) + { + ret = pNode[*pMBChar].mUCS2; + return true; + } + + return false; +} + +// add a mb char def to the chache +void cMBUCS2Cache::Add(mbchar_t* pMBchar, int mblen, dbchar_t ucs2) +{ + ASSERT(mblen > 0); + + Element* pNode = mTop; + while (mblen > 1); + { + // this ASSERT fails if there is a UCS2 definition for a mbchar + // whose first few bytes are identical to this char + ASSERT(pNode[*pMBchar].mElementDefinition == Element::UNDEFINED || + pNode[*pMBchar].mElementDefinition == Element::CONTINUES) + + if (pNode[*pMBchar].mElementDefinition == Element::UNDEFINED) + { + pNode[*pMBchar].mElementDefinition = Element::CONINUES; + pNode = pNode[*pMBchar].mpNext = new Element[256]; + } + else + { + pNode = pNode[*pMBchar].mpNext; + } + + --mblen; + ++pMBChar; + } + + // this assert makes sure everything is sane + ASSERT(pNode[*pMBchar].mElementDefinition == Element::UNDEFINED || + (pNode[*pMBchar].mElementDefinition == Element::UCS2 && pNode[*pMBchar].mUCS2 == ucs2)); + + // this assert fails if we attempt to add the same mbchar twice + ASSERT(pNode[*pMBchar].mElementDefinition == Element::UNDEFINED) + + pNode[*pMBchar].mElementDefinition = Element::UCS2; + pNode[*pMBchar].mUCS2 = ucs2; +} +*/ +/* +static inline const byte* tss_hash_key_convert()( const TCHAR* psz, int* const pcbKeyLen ) +{ + *pcbKeyLen = sizeof(TCHAR) * _tcslen( psz ); + return (byte*)psz; +} + +static inline bool tss_hash_key_compare()( const TCHAR* lhs, const TCHAR* rhs ) +{ + return ( _tcscmp( lhs, rhs ) == 0 ); +} + +cHashTable< dbchar_t*, + mbchar_t*, + tss_hash_key_convert, + tss_hash_key_compare > ha; + */ + + + diff --git a/src/core/stringutil.h b/src/core/stringutil.h new file mode 100644 index 0000000..c4540ba --- /dev/null +++ b/src/core/stringutil.h @@ -0,0 +1,205 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: stringutil.h +* Date....: 09/03/99 +* Creator.: +* +* Basic String Utilities +*/ + +#ifndef __STRINGUTIL_H +#define __STRINGUTIL_H + +#ifndef __WCHAR16_H +#include "core/wchar16.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//----------------------------------------------------------------------------- +// cStringUtil +// NOTE:RAD -- This should not be a class, changed to namespace. +// contains utility methods for manipulating strings +//----------------------------------------------------------------------------- +namespace cStringUtil +{ + //--Type Dispatched Conversion (Generalization away from TCHAR) + + /// Handle Like-Types (xstring to xstring) + + inline + const char * + Convert( std::string& lhs, const std::string& rhs ) + { + lhs = rhs; + return lhs.c_str(); + } + + /// Specialize Everything Else + + std::string::const_iterator + Convert( std::string&, const wc16_string& ); + + wc16_string::const_iterator + Convert( wc16_string&, const std::string& ); + +#if SUPPORTS_WCHART && WCHAR_REP_IS_UCS2 + + inline + std::wstring::const_iterator + Convert( std::wstring& lhs, const std::wstring& rhs ) + { + lhs = rhs; + return lhs.c_str(); + } + + std::wstring::const_iterator + Convert( std::wstring&, const wc16_string& ); + + std::wstring::const_iterator + Convert( std::wstring&, const std::string& ); + + std::string::const_iterator + Convert( std::string&, const std::wstring& ); + + wc16_string::const_iterator + Convert( wc16_string&, const std::wstring& ); + +#endif//SUPPORTS_WCHART + + + /// WARNING: These are deprecated, please use Convert()! + + std::string TstrToStr( const TSTRING& tstr ); + // converts a tstring to a narrow string; useful for passphrase input, which must always be + // the same format, regardless of what TCHAR is defined to. + + TSTRING StrToTstr( const std::string& str ); + // converts a narrow string to a TSTRING + + TSTRING WstrToTstr( const wc16_string& src ); + // convert wc16_string to a TSTRING + wc16_string TstrToWstr( const TSTRING& tstr ); + // convert a TSTRING to a wc16_string + + template + void splitstring(IterT& iter, + const TSTRING& str, + const TSTRING& delims) { + + TSTRING::size_type where; + TSTRING tmpStr; + TSTRING workingString = str; + + while (workingString.length() > 0) { + + where = workingString.find_first_of(delims, 0); + + // in the case of no delimeters, setp to + // grab the entire string. + // + if (where == TSTRING::npos) + where = workingString.length(); + + tmpStr = workingString.substr(0, where); + workingString.erase(0, where+1); + + iter.push_back(tmpStr); + + } + } + + + + +}//cStringUtil:: + + +//----------------------------------------------------------------------------- +// push_back_string +// +// push_back decorator for basic_string. +// allows basic_string to be used in, among other things, a back_insert_iterator +//----------------------------------------------------------------------------- +namespace std +{ + template< class E > + class push_back_string + : public basic_string + { + public: + //- - - - - - - - - - - - - - - - - - - - - - - - - - + // internal typedefs + //- - - - - - - - - - - - - - - - - - - - - - - - - - + typedef push_back_string _MyT; + typedef basic_string _ParentT; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - + // required typedef ( to be a container it must have this... ) + //- - - - - - - - - - - - - - - - - - - - - - - - - - + typedef typename _ParentT::value_type value_type; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - + // required constructors and assignment operators... + //- - - - - - - - - - - - - - - - - - - - - - - - - - + push_back_string( const _ParentT& rhs ) + : _ParentT( rhs ) + { + } + + push_back_string() + : _ParentT() + { + } + + _MyT& operator=( const _MyT& rhs ) + { + return _ParentT::operator=( rhs ); + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - + // this is it! + // makes the string look like a container to a back_insert_iterator.... + //- - - - - - - - - - - - - - - - - - - - - - - - - - + _MyT& push_back( const typename _ParentT::value_type& v ) + { + *this += v; return( *this ); + } + }; +} + + +#endif//__STRINGUTIL_H + diff --git a/src/core/stringutil_t.h b/src/core/stringutil_t.h new file mode 100644 index 0000000..3a9eb04 --- /dev/null +++ b/src/core/stringutil_t.h @@ -0,0 +1,174 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: stringutil_t.h +* Date....: 09/03/99 +* Creator.: rdifalco +* +* Tests String Utils +* +*/ + +#ifndef __STRINGUTIL_T_H +#define __STRINGUTIL_T_H + +#include "ntmbs.h" + +#if USING_NTDBS_STUFF +#include "ntdbs.h" +#endif // USING_NTDBS_STUFF + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Char traits for WCHAR16 (aka dbchar_t) and NTMBCS (mctype_t) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +inline +void TestStringUtil() +{ +#if USING_NTDBS_STUFF + cDebug db("Test std::char_traits"); + + db.TraceAlways("Entering...\n"); + + tss::dbstring a; + tss::dbstring b; + std::string c; // Control String + +//#if !IS_UNIX // need to get the L"" stuff working + + static char NTMBS1[] = { 65, 66, 67, 68, 0 }; + static dbchar_t NTDBS1[] = { 65, 66, 67, 68, 0 }; + static dbchar_t NTDBS2[] = { 40, 66, 67, 68, 0 }; + static dbchar_t NTDBS0[] = { 65, 66, 67, 68, 0, 0 }; + + c.assign( NTMBS1 ); + a.assign( NTDBS1 ); + + TEST( c == NTMBS1 ); + TEST( a == NTDBS1 ); + + a.resize( 0 ); + b.resize( 0 ); + + TEST( a.empty() ); + TEST( b.empty() ); + + a.assign( NTDBS1 ); + TEST( a.size() == 4); + TEST( std::equal( a.begin(), a.end(), NTDBS1 ) ); + TEST( b.size() == 0) ; + + a.resize( 3 ); + TEST( a.c_str() != b.c_str() ); + TEST( std::equal( a.begin(), a.end(), NTDBS1 ) ); + TEST( std::equal( b.begin(), b.end(), NTDBS1 ) ); + + a = NTDBS2; + b = a; + TEST( a == b ); + TEST( a.size() == b.size() ); + + TEST( a[0] == b[0] ); + TEST( a[1] == b[1] ); + TEST( a[2] == b[2] ); + TEST( a[3] == b[3] ); + + const tss::dbstring a1 = a; + const tss::dbstring b1 = b; + TEST( a1[0] == b1[0] ); + TEST( a1[1] == b1[1] ); + TEST( a1[2] == b1[2] ); + TEST( a1[3] == b1[3] ); + +#if 0 + try + { + TEST( a[4] > 0 ); + TEST( false ); // exception did not get thrown + } + catch ( std::out_of_range ) + { + ; + } +#endif + + //--Test Reference Counting + + tss::dbstring x( NTDBS1 ); + tss::dbstring ref = x; + + TEST( x.c_str() == ref.c_str() ); + TEST( x == ref ); + TEST( std::equal( x.begin(), x.end(), ref.begin() ) ); + TEST( x.size() == ref.size() ); + + + /////////////////////////// + // now test the crazy convert functions + + std::string singleStr, singleStrNull; + wc16_string wc16Str, wc16StrNull; + TSTRING tStr, tStrNull; + + // the four functions for reference + //std::string TstrToStr( const TSTRING& tstr ); + //TSTRING StrToTstr( const std::string& str ); + //TSTRING WstrToTstr( const wc16_string& src ); + //wc16_string TstrToWstr( const TSTRING& tstr ); + + // test Null assignments + singleStr = cStringUtil::TstrToStr( tStrNull ); + TEST(singleStr.length() == 0); + tStr = cStringUtil::StrToTstr( singleStrNull ); + TEST(tStr.length() == 0); + tStr = cStringUtil::WstrToTstr( wc16StrNull ); + TEST(tStr.length() == 0); + wc16StrNull = cStringUtil::TstrToWstr( tStrNull ); + TEST(wc16StrNull.length() == 0); + + // test copying some text around + singleStr = "123456789"; + tStr.erase(); tStr = cStringUtil::StrToTstr( singleStr ); + TEST(tStr.length() == 9); + wc16Str.resize(0); wc16Str = cStringUtil::TstrToWstr( tStr ); + TEST(wc16Str.length() == 9); + singleStr.erase(); singleStr = cStringUtil::TstrToStr( tStr ); + TEST(singleStr.length() == 9); + tStr.erase(); tStr = cStringUtil::WstrToTstr( wc16Str ); + TEST(tStr.length() == 9); + + db.TraceAlways("Done...\n"); +#endif // USING_NTDBS_STUFF +} + + +#endif//__STRINGUTIL_T_H diff --git a/src/core/tasktimer.h b/src/core/tasktimer.h new file mode 100644 index 0000000..6bf7de6 --- /dev/null +++ b/src/core/tasktimer.h @@ -0,0 +1,151 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// tasktimer.h +// +// cTaskTimer -- a class that can be used to time a given task +// TODO -- make this cross-platform -- maybe a template class with the time-reaping +// function as a parameter +#ifndef __TASKTIMER_H +#define __TASKTIMER_H + +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __DEBUG_H +#include "debug.h" +#endif + +#include + +/////////////////////////////////////////////////////////////////////////////// +// cTaskTimer -- +/////////////////////////////////////////////////////////////////////////////// +template +class cTaskTimer +{ +public: + cTaskTimer(const TSTRING& name) : mName(name), mTotalTime(0), mStartTime(0), mNumStarts(0) {} + ~cTaskTimer(); + + void Start(); + void Stop(); + bool IsRunning() { return (mStartTime != 0); } + void Reset() { mNumStarts = mStartTime = mTotalTime = 0 } + int32 GetTotalTime() const; + int32 GetNumTimesStarted() const; // returns the number of times start() was called + const std::string& GetName() const; + +private: + TSTRING mName; + int32 mTotalTime; + TIME_TYPE mStartTime; + int32 mNumStarts; +}; + + +#if IS_UNIX +/////////////////////////////////////////////////////////////////////////////// +// cUnixTimeFn -- Unix version, inserts proper function call and overloads +// operator() +/////////////////////////////////////////////////////////////////////////////// +#include +class cUnixTimeFn +{ +public: + typedef uint32 DataType; + + uint32 operator()() + { + return time( &dummy_var ); + } +private: + time_t dummy_var; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cUnixTaskTimer -- the Unix typedef... +/////////////////////////////////////////////////////////////////////////////// +typedef cTaskTimer cUnixTaskTimer; +typedef cUnixTaskTimer cGenericTaskTimer; + +#endif // IS_UNIX + +//----------------------------------------------------------------------------- +// inline implementation +//----------------------------------------------------------------------------- + +template +inline void cTaskTimer::Start() +{ + ASSERT(! IsRunning()); + TIME_FN GetTime; + mStartTime = GetTime(); + mNumStarts++; +} + +template +inline void cTaskTimer::Stop() +{ + ASSERT(IsRunning()); + TIME_FN GetTime; + mTotalTime += ( GetTime() - mStartTime ); + mStartTime = 0; +} + +template +inline int32 cTaskTimer::GetTotalTime() const +{ + return mTotalTime; +} + +template +inline const std::string& cTaskTimer::GetName() const +{ + return mName +} + +template +inline cTaskTimer::~cTaskTimer() +{ + // stop the timer if it is currently running + if(IsRunning()) + Stop(); + + // trace out the time contents... + cDebug d("cTaskTimer"); + d.TraceDebug("----- Time to execute %s: %d (started %d times)\n", mName.c_str(), mTotalTime, mNumStarts); +} + + +#endif + diff --git a/src/core/tasktimer_t.cpp b/src/core/tasktimer_t.cpp new file mode 100644 index 0000000..166bd10 --- /dev/null +++ b/src/core/tasktimer_t.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tasktimer_t -- test driver for cTaskTimer +#include "stdcore.h" + +#if IS_UNIX +void TestTaskTimer() +{ +} +#endif // IS_UNIX/WIN32 + diff --git a/src/core/tchar.h b/src/core/tchar.h new file mode 100644 index 0000000..d584123 --- /dev/null +++ b/src/core/tchar.h @@ -0,0 +1,134 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// tchar.h +// +// VCC version of TCHAR.H that is cross platform compatible between UNIX and +// Windows. +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Short Documentation: +// (put here at the top of the file so you don't have to go searching for it) +// +// Here are some of the important "T" versions of functions you should use +// when wishing to abstract single-byte/doublebyte chars using this header. +// +// Old Function/Symbol "T" version +// -------------------- ------------------------------------ +// char name[256]; TCHAR name[256]; +// printf("Hi there %s\n", name); _tprintf(_T("Hi there %s"), name); +// strlen(name); _tcslen(name); +// strcpy(name, "Dave"); _tcscpy(name, _T("Dave"); +// strcat(name, " the man"); _tcscat(name, _T(" the man")); +// sizeof(name) sizeof(name)/sizeof(TCHAR); (or countof(name), see macro below) +// string foo; (STL string) TSTRING foo; +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __TCHAR_H +#define __TCHAR_H + +// A little macro that's useful for finding the number of characters in a TCHAR ARRAY +#define countof( x ) ( sizeof( x ) / sizeof( x[0] ) ) + +#if IS_UNIX + + +#include +#include +#include +#include + + + +#define TCHAR char +#define _tmain main + +typedef std::string TSTRING; +typedef std::stringstream TSTRINGSTREAM; +typedef std::ostringstream TOSTRINGSTREAM; +typedef std::istringstream TISTRINGSTREAM; +typedef std::ostream TOSTREAM; +typedef std::istream TISTREAM; +typedef std::ofstream TOFSTREAM; +typedef std::ifstream TIFSTREAM; + +// iostream abstractions +#define TCIN std::cin +#define TCOUT std::cout +#define TCERR std::cerr + +// other functions +#define _ftprintf fprintf +#define _stprintf sprintf +#define _itot itoa +#define _ttoi atoi +#define _istdigit isdigit +#define _tcsftime strftime +#define _vtprintf vprintf +#define _vftprintf vfprintf +#define _topen open +#define _tfdopen fdopen +#define _tfopen fopen +#define _tmkdir mkdir +#define _tcscpy strcpy +#define _tgetenv getenv +#define _taccess access +#define _tcreat creat +#define _tunlink unlink +#define _tcscmp strcmp +#define _tcsicmp strcasecmp +#define _totlower tolower +#define _totupper toupper +#define _tcslen strlen +#define _tcscat strcat +#define _tcsncmp strncmp + +// other abstractions +#define TUNLINK unlink + +// string representation +#if defined(_T) + // run it right over with a bulldozer, tripwire doesn't seem + // to use ctype.h's _T -PH +#undef _T +#endif +#define _T(x) x + +// misc... +#define __cdecl + + +#endif // WIN32 + +#endif // __TCHAR_H + diff --git a/src/core/tchar_t.cpp b/src/core/tchar_t.cpp new file mode 100644 index 0000000..06aaa2b --- /dev/null +++ b/src/core/tchar_t.cpp @@ -0,0 +1,133 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdcore.h" + +#include +#include +#include + +#ifndef __DEBUG_H +#include "debug.h" +#endif + +TSTRING test_wost(int, const TSTRING&); +void test_wist(const TSTRING&, cDebug& d); + +void TestTCHAR() +{ + cDebug d("TestTCHAR()"); + + d.TraceDetail("Entering...\n"); + + //Testing TCOUT: + TCOUT<< _T("Simple test of TSTRING (and TCOUT) :\n\n"); + TCERR<< _T("This should show up on cerr"); + + TSTRING pString; + pString = _T("Hi Mom!"); + + d.TraceDetail("%s \n", pString.c_str() ); + d.TraceDetail("Isn't this cool?\n\n"); + + //Begin fun tests of string streams: + + TSTRINGSTREAM wst; + //can I declare it? + + TSTRING str; + str = _T("Kiteman"); + TSTRING test1 = _T("word"); + + d.TraceDetail("Testing TOSTRINGSTREAM with TSTRING:\n"); + TOSTRINGSTREAM ost(_T("test up")); + ost<>parse) + d.TraceDetail("%s \n", parse.c_str() ); +} + diff --git a/src/core/timebomb.cpp b/src/core/timebomb.cpp new file mode 100644 index 0000000..6fb5648 --- /dev/null +++ b/src/core/timebomb.cpp @@ -0,0 +1,87 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// timebomb.h +#include "stdcore.h" +#include "timebomb.h" +#include +#include +#include "timeconvert.h" +#include "corestrings.h" + +/////////////////////////////////////////////////////////////////////////////// +// TimeBombExploded() -- Call from main(). Prints out timebomb message and +// returns true if main() should exit. +// +bool TimeBombExploded() +{ + struct tm time_struct; + + /* + memset(&time_struct, 0, sizeof(time_struct)); + time_struct.tm_mday = 25; + time_struct.tm_mon = 0; + time_struct.tm_year = 99; + int64 begin = cTimeUtil::DateToTime( &time_struct ); + + memset(&time_struct, 0, sizeof(time_struct)); + time_struct.tm_mday = 1; + time_struct.tm_mon = 4; + time_struct.tm_year = 99; + int64 end = cTimeUtil::DateToTime( &time_struct ); + + int64 now = time(0); + + if (now < begin || now > end) + { + std::cerr << "This beta version of Tripwire(R) has expired.\n"; + return true; + } + */ + + // Many functions will fail as we approach the end of the epoch + // Rather than crashing, we will exit with a nice message + memset(&time_struct, 0, sizeof(time_struct)); + time_struct.tm_mday = 1; + time_struct.tm_mon = 0; + time_struct.tm_year = 138; + int64 endoftime = cTimeUtil::DateToTime( &time_struct ); + + if (time(0) > endoftime) + { + TCERR << TSS_GetString(cCore, core::STR_ENDOFTIME) << std::endl; + return true; + } + + return false; +} + diff --git a/src/core/timebomb.h b/src/core/timebomb.h new file mode 100644 index 0000000..b9030bc --- /dev/null +++ b/src/core/timebomb.h @@ -0,0 +1,45 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// timebomb.h + +#ifndef __TIMEBOMB_H +#define __TIMEBOMB_H + +/////////////////////////////////////////////////////////////////////////////// +// TimeBombExploded() -- Call from main(). Prints out timebomb message and +// returns true if main() should exit. +// +bool TimeBombExploded(); + +#endif + diff --git a/src/core/timeconvert.cpp b/src/core/timeconvert.cpp new file mode 100644 index 0000000..5508a79 --- /dev/null +++ b/src/core/timeconvert.cpp @@ -0,0 +1,83 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// timeconvert.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdcore.h" +#include "timeconvert.h" +#include "debug.h" +#include "stringutil.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include + +//========================================================================= +// METHOD CODE +//========================================================================= + +#define TIME_MAX 2147483647L // largest signed 32 bit number + +struct tm* cTimeUtil::TimeToDateGMT( const int64& seconds ) +{ + ASSERT( seconds < TIME_MAX );// this assumes time_t size is 32 bit. Yikes! + time_t t = static_cast(seconds); + return gmtime( &t ); +} + +struct tm* cTimeUtil::TimeToDateLocal( const int64& seconds ) +{ + ASSERT( seconds < TIME_MAX );// this assumes time_t size is 32 bit. Yikes! + time_t t = static_cast(seconds); + tzset(); + return localtime( &t ); +} + +int64 cTimeUtil::DateToTime( struct tm* ptm ) +{ + tzset(); + return mktime( ptm ); +} + +int64 cTimeUtil::GetTime() +{ + return time( NULL ); +} + + diff --git a/src/core/timeconvert.h b/src/core/timeconvert.h new file mode 100644 index 0000000..c8cb1a1 --- /dev/null +++ b/src/core/timeconvert.h @@ -0,0 +1,76 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// timeconvert.h + +#ifndef __TIMECONVERT_H +#define __TIMECONVERT_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +// wrapper for time.h functions +// +// NOTE:BAM -- this only works with a time_t that is less than 64 bits long. +class cTimeUtil +{ +public: + static int64 DateToTime( struct tm* ptm ); + // simple conversion. ptm is considered to be in localtime. + static struct tm* TimeToDateGMT( const int64& seconds ); + // simple conversion + static struct tm* TimeToDateLocal( const int64& seconds ); + // conversion with timezone and daylight + static int64 GetTime(); + // returns current time in UTC +}; + +#endif//__TIMECONVERT_H + diff --git a/src/core/tw_signal.cpp b/src/core/tw_signal.cpp new file mode 100644 index 0000000..48dfa5b --- /dev/null +++ b/src/core/tw_signal.cpp @@ -0,0 +1,119 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tw_signal.cpp +#include "stdcore.h" +#include "tw_signal.h" +#include "corestrings.h" +#include +#include + +static void util_SignalHandler( int sig ); + +#if IS_UNIX +static void tw_psignal( int sig, const TCHAR* s ); +#endif + +tw_sighandler_t tw_signal(int sig, tw_sighandler_t pFunc) +{ + return signal(sig, pFunc); +} + +int tw_raise(int sig) +{ + return raise(sig); +} + +tw_sighandler_t tw_sigign(int sig) +{ + return signal(sig, SIG_IGN); +} + +////////////////////////////////////////////////////////////////////// +// tw_HandleSignal -- Take a given signal and install a handler for +// it, which will then exit with the supplied exit value +tw_sighandler_t tw_HandleSignal( int sig ) +{ + return signal( sig, util_SignalHandler ); +} + +void util_SignalHandler( int sig ) +{ + //If we're on unix, let's print out a nice error message telling + //the user which signal we've recieved. +#if IS_UNIX + tw_psignal( sig, (TSS_GetString( cCore, core::STR_SIGNAL).c_str() ) ); +#endif + + exit( 8 ); +} + +#if IS_UNIX +void tw_psignal(int sig, const TCHAR *str) +{ + TCHAR *siglist[NSIG] = { + _T("Unknown Signal"), + _T("Hangup"), + _T("Interrupt"), + _T("Quit"), + _T("Illegal Instruction"), + _T("Trace/Breakpoint Trap"), + _T("Abort"), + _T("Emulation Trap"), + _T("Arithmetic Exception"), + _T("Killed"), + _T("Bus Error"), + _T("Segmentation Fault"), + _T("Bad System Call"), + _T("Broken Pipe"), + _T("Alarm Clock"), + _T("Terminated"), + _T("User Signal 1"), + _T("User Signal 2"), + _T("Child Status Changed"), + _T("Power-Fail/Restart"), + _T("Virtual Timer Expired"), + _T("Profiling Timer Expired"), + _T("Pollable Event"), + _T("Window Size Change"), + _T("Stopped (signal)"), + _T("Stopped (user)"), + _T("Continued"), + _T("Stopped (tty input)"), + _T("Stopped (tty output)"), + _T("Urgent Socket Condition"), + _T("File Lock Lost") + }; + + _ftprintf(stderr, _T("%s %s\n"), str, sig < NSIG ? siglist[sig] : siglist[0]); +} +#endif + diff --git a/src/core/tw_signal.h b/src/core/tw_signal.h new file mode 100644 index 0000000..5361199 --- /dev/null +++ b/src/core/tw_signal.h @@ -0,0 +1,67 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// tw_signal.h -- a wrapper around signal(), needed because of linux +// build issues +// +#ifndef __TW_SIGNAL_H +#define __TW_SIGNAL_H + +#include + +#ifdef HAVE_SIGNUM_H +#include // the signal number constants +#endif +#ifdef HAVE_BITS_SIGNUM_H +#include +#endif + +extern "C" { +typedef void (*tw_sighandler_t)(int); +} + +tw_sighandler_t tw_signal(int sig, tw_sighandler_t pFunc); +int tw_raise (int sig); + +/////////////////////////////////////////////////////////////////////////////// +// tw_sigign -- wrapper around tw_signal(XXX, SIG_IGN) +// +tw_sighandler_t tw_sigign(int sig); + +/////////////////////////////////////////////////////////////////////////////// +// tw_HandleSignal --wrapper around signal( XXX, ) +// +tw_sighandler_t tw_HandleSignal( int sig ); + + +#endif //__TW_SIGNAL_H + diff --git a/src/core/twlimits.cpp b/src/core/twlimits.cpp new file mode 100644 index 0000000..9da1234 --- /dev/null +++ b/src/core/twlimits.cpp @@ -0,0 +1,99 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twlimits.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= +#include "stdcore.h" +#include "twlimits.h" +#include "debug.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +bool cInterpretInt::InterpretInt( const TSTRING& str, int* pi ) +{ + ASSERT( pi != 0); + + bool fFormatOK = true; + + // + // make sure string is not longer than a string representation of LIMIT_MAX + // + TOSTRINGSTREAM sstr; + sstr << cInterpretInt::LIMIT_MAX; + if( str.length() > sstr.str().length() ) + fFormatOK = false; + + // + // make sure string is not too short + // + if( fFormatOK && str.length() <= 0 ) + fFormatOK = false; + + // + // make sure first character is a digit or the minus sign + // + if( fFormatOK ) + { + if( ! ( _T('-') == str[0] || std::isdigit( str[0], std::locale() ) ) ) + fFormatOK = false; + } + + // + // make sure all other characters are digits + // NOTE:BAM -- this assumes that all digits in all locales are SB characters. + // TODO:BAM -- check this... + for( TSTRING::size_type j = 1; fFormatOK && j < str.length(); j++ ) + { + if( ! std::isdigit( str[j], std::locale() ) ) + fFormatOK = false; + } + + // + // do _ttoi conversion and check that it is within allowable limits + // + if( fFormatOK ) + { + *pi = _ttoi( str.c_str() ); + + if( *pi < GetMin() || *pi > GetMax() ) + fFormatOK = false; + } + + return fFormatOK; +} + diff --git a/src/core/twlimits.h b/src/core/twlimits.h new file mode 100644 index 0000000..1182ad0 --- /dev/null +++ b/src/core/twlimits.h @@ -0,0 +1,126 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twlimits.h +// +// this file contains classes that contain informations regarding +// "limits" that need to be shared between files. The classes should only +// contain minimal functionality in support of these limits. +// +// + +#ifndef __TWLIMITS_H +#define __TWLIMITS_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + + +/////////////////////////////////////////////// +// cInterpretInt +/////////////////////////////////////////////// +// +// override GetMin() and GetMax() to have different +// limits +// +/////////////////////////////////////////////// +class cInterpretInt +{ +public: + // + // basic functionality + // + bool InterpretInt( const TSTRING& str, int* pi ); + // converts the string into an int value, returned in *pi. + // returns true if successfully converted value. + // *pi is undefined if function returns false. + +private: + // + // private enums + // + enum Limits + { + LIMIT_MIN = INT_MIN, + LIMIT_MAX = INT_MAX + }; + + // + // private functionality + // + virtual int GetMax() { return LIMIT_MAX; }; + virtual int GetMin() { return LIMIT_MIN; }; +}; + +/////////////////////////////////////////////// +// cSeverityLimits +/////////////////////////////////////////////// +class cSeverityLimits : public cInterpretInt +{ +private: + enum Limits + { + LIMIT_MIN = 0, + LIMIT_MAX = 1000000 + }; + + virtual int GetMax() { return LIMIT_MAX; }; + virtual int GetMin() { return LIMIT_MIN; }; +}; + +/////////////////////////////////////////////// +// cRecurseDepthLimits +/////////////////////////////////////////////// +class cRecurseDepthLimits : public cInterpretInt +{ +private: + enum Limits + { + LIMIT_MIN = -1, + LIMIT_MAX = 1000000 + }; + + virtual int GetMax() { return LIMIT_MAX; }; + virtual int GetMin() { return LIMIT_MIN; }; +}; + +#endif //__TWLIMITS_H + diff --git a/src/core/twlocale.cpp b/src/core/twlocale.cpp new file mode 100644 index 0000000..b528eca --- /dev/null +++ b/src/core/twlocale.cpp @@ -0,0 +1,325 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twlocale.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= +#include "stdcore.h" +#include "twlocale.h" +#include "corestrings.h" + +//TODO:mdb -- for some reason, this isn't being included on gcc/stlport +// How is this being included for other platforms (I can't find +// references to locale.h anywhere in the code!) +// +#if HAVE_GCC +#include +#endif //HAVE_GCC + + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + + +//========================================================================= +// UTIL FUNCTION PROTOTYPES +//========================================================================= + +static TSTRING& util_FormatTimeC( struct tm* ptm, TSTRING& strBuf ); +static TSTRING& util_FormatTimeCPlusPlus( struct tm* ptm, TSTRING& strBuf ); +static TSTRING& util_FormatTime( struct tm* ptm, TSTRING& strBuf ); + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + + +void cTWLocale::InitGlobalLocale() +{ + cDebug d("cTWLocale::InitGlobalLocale"); + + d.TraceDetail( "Attempting to set the program locale from the" + "default \"C\" locale to the system-default locale." ); + +#if USE_CLIB_LOCALE + char* pchLocale = setlocale( LC_ALL, "" ); + + d.TraceDetail( "C++ locale is incomplete or unavailable with this compiler, so" + "only changing the C-language locale. Some C++ locale-specific functionality" + "may not function properly." ); + + if( pchLocale ) + { + d.TraceDebug( "locale changed to the system-default locale (non-C++): <%s>\n", pchLocale ); + } + else + { + d.TraceDebug( "Error: unable to change locale to the system-default.\n" + "It is possible that there is no other locale than\n" + "the \"C\" locale on this platform.\n" ); + } +#else + std::locale l(""); + std::locale::global( l ); + d.TraceDebug( "locale changed to the system default std::locale (C++): <%s>\n", l.name().c_str() ); +#endif + +} + +TSTRING cTWLocale::FormatNumberAsHex( int32 i ) +{ + // + // preconditions + // + ASSERT( sizeof( long ) >= sizeof( int32 ) ); // must be able to cast to 'long' + + // + // convert long to a string + // + TOSTRINGSTREAM sstr; + sstr.imbue( std::locale::classic() ); + sstr.setf( std::ios_base::hex, std::ios_base::basefield ); + const std::num_put< TCHAR > *pnp = 0, &np = tss::GetFacet( sstr.getloc(), pnp ); + np.put( sstr, sstr, sstr.fill(), (long)i ); + + // + // return it + // + return( sstr.str() ); +} + +template< class numT, class CharT > +class cFormatNumberUtil +{ +public: + + // TODO:BAM -- these functions should really maybe take a stringstream that has been + // already set up for formatting (basefield, locale, etc.) that way we can merge + //. the FormatNumberAsHex function as well + // + //============================================================================= + // template< class numT, class CharT > + // numT + // cFormatNumberUtil::FormatNumber( const std::basic_string< CharT >& s, bool fCStyleFormatting = false ) + //----------------------------------------------------------------------------- + // EFFECTS: Does all actual formatting for FormatNumber methods + static + numT + Format( const std::basic_string< CharT >& s, bool fCStyleFormatting ) + { + static const std::num_get< CharT >* png; + std::basic_istringstream< CharT > ss( s ); + std::ios_base::iostate state; + numT n; + + if( fCStyleFormatting ) + ss.imbue( std::locale::classic() ); + + tss::GetFacet( ss.getloc(), png ).get( + ss, + std::istreambuf_iterator< CharT >(), + ss, + state, + n ); + + + if( ( state & std::ios_base::failbit ) != 0 ) + throw eTWLocaleBadNumFormat(); + + return( n ); + } + + //============================================================================= + // std::basic_string< CharT >& + // Format( numT n, std::basic_string< CharT >& sBuf ) + //----------------------------------------------------------------------------- + // EFFECTS: Does all actual formatting for FormatNumber methods + // + static + std::basic_string< CharT >& + Format( numT n, std::basic_string< CharT >& sBuf, bool fCStyleFormatting = false ) + { + static const std::num_put< CharT >* pnp; + std::basic_ostringstream< CharT > ss; + + if( fCStyleFormatting ) + ss.imbue( std::locale::classic() ); + + tss::GetFacet( ss.getloc(), pnp ).put( ss, ss, ss.fill(), n ); + + sBuf = ss.str(); + return( sBuf ); + } +}; + +TSTRING cTWLocale::FormatNumberClassic( int32 i ) +{ + TSTRING s; + return cFormatNumberUtil< long, TCHAR >::Format( i, s, true ); +} + +int32 cTWLocale::FormatNumberClassic( const TSTRING& s ) +{ + return cFormatNumberUtil< long, TCHAR >::Format( s, true ); +} + + +TSTRING& cTWLocale::FormatNumber( uint64 ui, TSTRING& strBuf ) +{ + // try to use the int64 version + if( ui <= (uint64)TSS_INT64_MAX ) + return( FormatNumber( (int64)ui, strBuf ) ); + else + { + #if IS_MSVC + // MSVC can't convert from uint64 to a double for some reason + strBuf = TSS_GetString( cCore, core::STR_NUMBER_TOO_BIG ); + return( strBuf ); + #else + ASSERT( std::numeric_limits::max() >= TSS_UINT64_MAX ); + return( cFormatNumberUtil< double, TCHAR >::Format( (double)ui, strBuf ) ); + #endif + } +} + +TSTRING& cTWLocale::FormatNumber( int64 i, TSTRING& strBuf ) +{ + // try to use the int32 version + if( i <= (int64)TSS_INT32_MAX ) + return( FormatNumber( (int32)i, strBuf ) ); + else + { + ASSERT( std::numeric_limits::max() >= TSS_INT64_MAX ); + return( cFormatNumberUtil< double, TCHAR >::Format( (double)i, strBuf ) ); + } +} + +TSTRING& cTWLocale::FormatNumber( uint32 ui, TSTRING& strBuf ) +{ + ASSERT( sizeof(unsigned long) >= sizeof(uint32) ); // must be able to cast to 'ulong' + return( cFormatNumberUtil< unsigned long, TCHAR >::Format( (unsigned long)ui, strBuf ) ); +} + +TSTRING& cTWLocale::FormatNumber( int32 i, TSTRING& strBuf ) +{ + ASSERT( sizeof(long) >= sizeof(int32) ); // must be able to cast to 'long' + return( cFormatNumberUtil< long, TCHAR >::Format( (long)i, strBuf ) ); +} + +TSTRING& cTWLocale::FormatTime( int64 t, TSTRING& strBuf ) +{ + // clear return string + strBuf.erase(); + + tzset(); + time_t tmpTime = t; + struct tm * ptm = localtime( &tmpTime ); + if( ptm ) + { + util_FormatTime( ptm, strBuf ); + } + else + { + strBuf = TSS_GetString( cCore, core::STR_UNKNOWN_TIME ); + } + + return( strBuf ); +} + +//========================================================================= +// UTIL FUNCTION IMPLEMENTATION +//========================================================================= + +TSTRING& util_FormatTime( struct tm* ptm, TSTRING& strBuf ) +{ + ASSERT( ptm ); + + #if USES_CLIB_DATE_FUNCTION + + return util_FormatTimeC( ptm, strBuf ); + + #else + + return util_FormatTimeCPlusPlus( ptm, strBuf ); + + #endif +} + + +TSTRING& util_FormatTimeCPlusPlus( struct tm* ptm, TSTRING& strBuf ) +{ + ASSERT( ptm ); + TOSTRINGSTREAM sstr; + static const std::time_put* ptp; + + // + // format date + // + #if IS_MSVC // MSVC uses old put() signature which didn't have the fill character, (and uses proprietary '#') + tss::GetFacet( sstr.getloc(), ptp ).put( sstr, sstr, ptm, 'c', '#' ); + #else + tss::GetFacet( sstr.getloc(), ptp ).put( sstr, sstr, sstr.fill(), ptm, 'c' ); + #endif + + strBuf = sstr.str(); + return strBuf; +} + + +TSTRING& util_FormatTimeC( struct tm* ptm, TSTRING& strBuf ) +{ + ASSERT( ptm ); + + TCHAR achTimeBuf[256]; + + /* XXX: This should check (#ifdef) for strftime - PH */ + size_t nbWritten = _tcsftime( achTimeBuf, countof( achTimeBuf ), + + #if IS_MSVC // MSVC uses proprietary '#' + _T("%#c"), + #else + _T("%c"), + #endif + ptm ); + + if( nbWritten ) + strBuf = achTimeBuf; + else + strBuf = TSS_GetString( cCore, core::STR_UNKNOWN_TIME ); + + return strBuf; +} + diff --git a/src/core/twlocale.h b/src/core/twlocale.h new file mode 100644 index 0000000..4fb236c --- /dev/null +++ b/src/core/twlocale.h @@ -0,0 +1,120 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twlocale.h +// + +#ifndef __TWLOCALE_H +#define __TWLOCALE_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +TSS_EXCEPTION( eTWLocale, eError ); +TSS_EXCEPTION( eTWLocaleBadNumFormat, eError ); + +/////////////////////////////////////////////// +// cTWLocale +/////////////////////////////////////////////// +// +// contains: +// Utility functions that are wrappers for +// facet functionality. +// +/////////////////////////////////////////////// +class cTWLocale +{ +public: + static void InitGlobalLocale(); + // initializes global locale to the default locale + + // + // basic functionality + // + static TSTRING& FormatNumber( int32 i, TSTRING& strBuf ); + static TSTRING& FormatNumber( int64 i, TSTRING& strBuf ); + static TSTRING& FormatNumber( uint32 ui, TSTRING& strBuf ); + static TSTRING& FormatNumber( uint64 ui, TSTRING& strBuf ); + static TSTRING& FormatNumber( double d, TSTRING& strBuf ); + // returns the locale-specific representation of the given cardinal number + + static TSTRING FormatNumberClassic( int32 i ); + static int32 FormatNumberClassic( const TSTRING& s ); + // returns the C-locale representation of the given cardinal number + + static TSTRING FormatNumberAsHex( int32 x ); + // locale-independant + + static TSTRING& FormatTime( int64 t, TSTRING& strBuf ); + // returns the local time and date formatted according to the current locale. + // t is the number of seconds elapsed since midnight (00:00:00), + // January 1, 1970, coordinated universal time +}; + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + +namespace tss +{ + //////////////////////////////////////////////// + // GetFacet + // + // Abstracts std::use_facet since Win32 and KAI + // each implement it in a non-standard way. + //////////////////////////////////////////////// + template< class FacetT > inline const FacetT& GetFacet( const std::locale& l, const FacetT* pf ) + { +#if USE_STD_CPP_LOCALE_WORKAROUND + return std::use_facet( l, pf ); +#else + return std::use_facet< FacetT >( l ); pf; // This is C++ standard +#endif + } +} + +#endif //__TWLOCALE_H + + diff --git a/src/core/twlocale_t.cpp b/src/core/twlocale_t.cpp new file mode 100644 index 0000000..fb83bef --- /dev/null +++ b/src/core/twlocale_t.cpp @@ -0,0 +1,227 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twlocale_t.h +// Date....: 07/26/99 +// Creator.: Brian McFeely (bmcfeely) +// +// Tests the cTWLocale class +// + +#include "stdcore.h" +#include "debug.h" +#include "core/twlocale.h" + +void TestAtoi(); +void TestItoa(); +void TestFlags(); +void TestRoundtrip(); +void TestHex(); + +#define ASSERT_THAT_IT_THROWS( x, error ) \ + try \ + { \ + x; \ + ASSERT( false ); \ + } catch( error& ) {} + +void TestTWLocale() +{ +#ifdef DOESNTWORK + TestHex(); + TestAtoi(); + TestItoa(); + TestFlags(); + TestRoundtrip(); +#endif//NOTDONE +} + +#ifdef DOESNTWORK + +void TestAtoi() +{ + // + // setup + // + int32 n; + TSTRING str = _T("123456"); + + // + // Try formatting with our default locale + // + cTWLocale::InitGlobalLocale(); + n = cTWLocale::FormatNumber( str ); + ASSERT( n == 123456 ); + + // + // Try formatting with "" locale + // + std::locale::global( std::locale("") ); + n = cTWLocale::FormatNumber( str ); + ASSERT( n == 123456 ); + + // + // Try formatting with "C" locale + // + std::locale::global( std::locale("") ); + n = cTWLocale::FormatNumber( str ); + ASSERT( n == 123456 ); +} + +void TestItoa() +{ + // + // can't do ASSERT( str == _T("123456") ) + // because locale may turn it into "123,465" or whatever + // + + // + // setup + // + int32 n = 123456; + TSTRING str; + + // + // Try formatting with our default locale + // + cTWLocale::InitGlobalLocale(); + cTWLocale::FormatNumber( n, str ); + TCOUT << str << std::endl; + + // + // Try formatting with "" locale + // + std::locale::global( std::locale("") ); + cTWLocale::FormatNumber( n, str ); + TCOUT << str << std::endl; + + // + // Try formatting with "C" locale + // + std::locale::global( std::locale("") ); + cTWLocale::FormatNumber( n, str ); + TCOUT << str << std::endl; +} + +void TestRoundtrip() +{ + // + // init + // + cTWLocale::InitGlobalLocale(); + + // + // atoitoa + // + TSTRING strIn = _T("123456"); + TSTRING strOut; + strOut = cTWLocale::FormatNumber( cTWLocale::FormatNumber( strIn ), strOut ); + // don't know if string will be the same due to possible changes in formatting from locale + // ASSERT( strOut == strIn ); <---- can't do this ^^^ + ASSERT( 123456 == cTWLocale::FormatNumber( strOut ) ); + + + // + // itoatoi + // + int32 nIn = 654321; + int32 nOut; + nOut = cTWLocale::FormatNumber( cTWLocale::FormatNumber( nIn, strIn ) ); + ASSERT( nOut == nIn ); +} + + +void TestFlags() +{ + // + // init + // + cTWLocale::InitGlobalLocale(); + + // + // hex + // + TSTRING str = _T("FF"); + int n = cTWLocale::FormatNumber( str, std::ios_base::hex ); + ASSERT( n == 0xFF ); + + // + // bad number for dec + // + ASSERT_THAT_IT_THROWS( cTWLocale::FormatNumberAsHex( str ), eError ); + + // + // oct + // + TSTRING strOct = _T("0712"); + n = cTWLocale::FormatNumber( strOct, std::ios_base::oct ); + ASSERT( n == 0712 ); + + // + // oct again + // + strOct = _T("00712"); + n = cTWLocale::FormatNumber( strOct, std::ios_base::oct ); + ASSERT( n == 0712 ); + + // + // oct again again + // + strOct = _T("712"); + n = cTWLocale::FormatNumber( strOct, std::ios_base::oct ); + ASSERT( n == 0712 ); + + // + // try bad oct + // + ASSERT_THAT_IT_THROWS( cTWLocale::FormatNumber( _T("99"), std::ios_base::oct ), eError ); +} + + +void TestHex() +{ + TSTRING str; + + str = cTWLocale::FormatNumberAsHex( 0x1234 ); + ASSERT( str == _T("1234") ); + + str = cTWLocale::FormatNumberAsHex( 16 ); + ASSERT( str == _T("10") ); + + str = cTWLocale::FormatNumberAsHex( 0x12344321 ); + ASSERT( str == _T("12344321") ); + + str = cTWLocale::FormatNumberAsHex( 0xFFFFFFFF ); + ASSERT( str == _T("FFFFFFFF") || str == _T("ffffffff") ); +} +#endif//DOESNTWORK + diff --git a/src/core/twstringslang.h b/src/core/twstringslang.h new file mode 100644 index 0000000..30f4f7d --- /dev/null +++ b/src/core/twstringslang.h @@ -0,0 +1,45 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twastringslang.h -- language enums for tripwire strings +// + +#ifndef __TWSTRINGSLANG_H +#define __TWSTRINGSLANG_H + +enum Languages +{ + LANG_USENGLISH = 1 +}; + +#endif + diff --git a/src/core/typed.h b/src/core/typed.h new file mode 100644 index 0000000..f32afbc --- /dev/null +++ b/src/core/typed.h @@ -0,0 +1,145 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// typed.h +// +// cType -- object that represents a class's type +// iTyped -- interface to implement to have a cType +#ifndef __TYPED_H +#define __TYPED_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +class cType +{ +public: + cType(const TCHAR* name); + + const TCHAR* AsString() const; + bool operator==(const cType& rhs) const; + bool operator!=(const cType& rhs) const; +private: + TSTRING mString; +}; + +class iTyped +{ +public: + virtual const cType& GetType() const = 0; + // the type of an FCO; classes that implement this interface need to + // (a) declare a public static const cType member mType and + // (b) returning that object in their implementation of GetType() + // You can use the macros below to simplify the process + + #ifdef _SUNPRO + ~iTyped(); + #endif +}; + +////////////////////////////////////////////// +// convenience macros for implementing iTyped +////////////////////////////////////////////// +#define DECLARE_TYPED()\ +public:\ +static const cType mType;\ +virtual const cType& GetType() const; + // put DECLARE_TYPED in the class definition + +#define IMPLEMENT_TYPED(CLASS, STRING)\ +const cType CLASS::mType(STRING);\ +const cType& CLASS::GetType() const\ +{\ + return mType;\ +} + // put IMPLEMENT_TYPED in the .cpp file where the class is implemented + +#define CLASS_TYPE(CLASS) CLASS::mType + // a convienent way to specify a class's type + +/////////////////////////////////////////////// +// iTyped Example +/////////////////////////////////////////////// +/* + (foo.h) + class cFoo : public iTyped + { + public: + DECLARE_TYPED() + } + + (foo.cpp) + DECLARE_TYPED(cFoo, "Foo"); + + (main.cpp) + int main() + { + iTyped* pi = Bar(); // returned a cFoo + cout << "Encountered class " << pi->GetType().AsString() << endl; + // prints "Encountered class Foo" + if(pi->GetType() == CLASS_TYPE(cFoo)) + { + cFoo* pFoo = static_cast(pi); + // cast is always safe + } + } +*/ + +/////////////////////////////////////////////////////////////////////////////// +// inline implementation +/////////////////////////////////////////////////////////////////////////////// +inline cType::cType(const TCHAR* name) : + mString(name) +{ + ASSERT(!mString.empty()); +} + + +inline const TCHAR* cType::AsString() const +{ + return mString.c_str(); +} + +inline bool cType::operator==(const cType& rhs) const +{ + return (this == &rhs); +} + +inline bool cType::operator!=(const cType& rhs) const +{ + return (this != &rhs); +} + + +#endif //__TYPED_H + diff --git a/src/core/types.h b/src/core/types.h new file mode 100644 index 0000000..fc7049b --- /dev/null +++ b/src/core/types.h @@ -0,0 +1,191 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// types.h -- place to abstract platform-specific type sizes +#ifndef __TYPES_H +#define __TYPES_H + +#include "platform.h" + +//----------------------------------------------------------------------------- +// standard TSS types +//----------------------------------------------------------------------------- + +typedef unsigned char byte ; // platform-independent + +typedef signed char int8 ; +typedef short int16 ; +typedef float float32 ; +typedef double float64 ; +typedef unsigned char uint8 ; +typedef unsigned short uint16 ; + +#if SIZEOF_INT == 4 +typedef int int32 ; +typedef unsigned int uint32 ; +#elif SIZEOF_LONG == 4 +typedef long int32 ; +typedef unsigned long uint32 ; +#else +# error "I don't seem to have a 32-bit integer type on this system." +#endif + +#if SIZEOF_LONG == 8 +typedef long int64 ; +typedef unsigned long uint64 ; +#elif SIZEOF_LONG_LONG == 8 +typedef long long int64 ; +typedef unsigned long long uint64 ; +#else +# error "I don't seem to have a 64-bit integer type on this system." +#endif + +// other Win32 definitions +//typedef uint16 UINT; +//typedef uint32 DWORD; + +//----------------------------------------------------------------------------- +// Limits -- should be platform independent, right? ( assumes 2's complement numbers ) +//----------------------------------------------------------------------------- + + +#if (!(USES_2S_COMPLEMENT)) + #error limits.h depends on 2s complement integers. Check core/types.h +#endif + +#include // defines limits for built-in types + +#define TSS_INT8_MIN (-127 - 1) +#define TSS_INT8_MAX 127 +#define TSS_UINT8_MAX 0xFFU +#define TSS_INT16_MIN (-32767 - 1) +#define TSS_INT16_MAX 32767 +#define TSS_UINT16_MAX 0xFFFFU +#define TSS_INT32_MIN (-2147483647 - 1) +#define TSS_INT32_MAX 2147483647 +#define TSS_UINT32_MAX 0xFFFFFFFFU +#define TSS_INT64_MIN (-9223372036854775807LL - 1) +#define TSS_INT64_MAX 9223372036854775807LL +#define TSS_UINT64_MAX 0xFFFFFFFFFFFFFFFFULL + +/* +//----------------------------------------------------------------------------- +// numeric_limits : TODO:BAM eventually I should get around to finishing these.... +//----------------------------------------------------------------------------- + +#pragma warning( push ) +pragma warning( disable: 4663 ) // Use new template specialization syntax: template<> +#define NOMINMAX // turn off min() and max() macros +#include +#pragma warning( pop ) + +// +// define numeric_limits for our types +// +// NOTE: assumes std::numeric_limits< int > does not depend on signedness of type +// TODO:BAM -- add members like digits and digits10 +// TODO:BAM -- define floating point numeric_limits +#define DECLARE_INTEGRAL_NUM_LIMITS( intT, minVal, maxVal, nDigits, ) \ + template<> class numeric_limits< intT > : public std::numeric_limits< int > \ + {\ + static intT (min)() throw() { return ( minVal ); } \ + static intT (max)() throw() { return ( maxVal ); } \ + enum { digits = 0 }; + enum { digits = 0 }; + }; + +// NOTE: assumes ( std::numeric_limits< int >::is_specialized == true ) +namespace std +{ +#if IS_UNIX + DECLARE_INTEGRAL_NUM_LIMITS( int8, SCHAR_MIN, SCHAR_MAX ); + DECLARE_INTEGRAL_NUM_LIMITS( int16, SHRT_MIN, SHRT_MAX ); + DECLARE_INTEGRAL_NUM_LIMITS( int32, LONG_MIN, LONG_MAX ); + +#endif +} +*/ + +//----------------------------------------------------------------------------- +// Byte Swapping +//----------------------------------------------------------------------------- + +inline int16 SWAPBYTES16(int16 i) +{ + + return ((uint16)i >> 8) | ((uint16)i << 8); + +} + +inline int32 SWAPBYTES32(int32 i) +{ + return ((uint32)i >> 24) | + (((uint32)i & 0x00ff0000) >> 8) | + (((uint32)i & 0x0000ff00) << 8) | + ((uint32)i << 24); +} + +inline int64 SWAPBYTES64(int64 i) +{ + return ((uint64)i >> 56) | + (((uint64)i & 0x00ff000000000000ULL) >> 40) | + (((uint64)i & 0x0000ff0000000000ULL) >> 24) | + (((uint64)i & 0x000000ff00000000ULL) >> 8) | + (((uint64)i & 0x00000000ff000000ULL) << 8) | + (((uint64)i & 0x0000000000ff0000ULL) << 24) | + (((uint64)i & 0x000000000000ff00ULL) << 40) | + ((uint64)i << 56); +} + + +#ifdef WORDS_BIGENDIAN + +#define tw_htonl(x) (x) +#define tw_ntohl(x) (x) +#define tw_htons(x) (x) +#define tw_ntohs(x) (x) +#define tw_htonll(x) (x) // int64 versions +#define tw_ntohll(x) (x) + +#else //!WORDS_BIGENDIAN + +#define tw_htonl(x) SWAPBYTES32((x)) +#define tw_ntohl(x) SWAPBYTES32((x)) +#define tw_htons(x) SWAPBYTES16((x)) +#define tw_ntohs(x) SWAPBYTES16((x)) +#define tw_htonll(x) SWAPBYTES64((x)) // int64 versions +#define tw_ntohll(x) SWAPBYTES64((x)) + +#endif //WORDS_BIGENDIAN + +#endif // __TYPES_H + diff --git a/src/core/types_t.cpp b/src/core/types_t.cpp new file mode 100644 index 0000000..85afebc --- /dev/null +++ b/src/core/types_t.cpp @@ -0,0 +1,52 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// types_t.cpp + +#include "stdcore.h" +#include "types.h" +#include "test/test.h" + +// TestTypes() -- this will simply make sure that all the types are defined properly for the current build +void TestTypes() +{ + TEST(sizeof(int8) == 1); + TEST(sizeof(uint8) == 1); + TEST(sizeof(int16) == 2); + TEST(sizeof(uint16) == 2); + TEST(sizeof(int32) == 4); + TEST(sizeof(uint32) == 4); + TEST(sizeof(int64) == 8); + TEST(sizeof(uint64) == 8); + TEST(sizeof(float32) == 4); + TEST(sizeof(float64) == 8); +} diff --git a/src/core/unixexcept.cpp b/src/core/unixexcept.cpp new file mode 100644 index 0000000..92d7b21 --- /dev/null +++ b/src/core/unixexcept.cpp @@ -0,0 +1,84 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// unixexcept.cpp +#include "stdcore.h" +#include "debug.h" +#include "unixexcept.h" +#include "debug.h" + +#include + +// TODO: JEB: make this look like eFileError +eUnix::eUnix( const TCHAR* szFunctionName, const TCHAR* szObjectName, bool fCallGetLastError) +: eError( _T("")) +{ +#if IS_UNIX + ASSERT( szFunctionName || szObjectName || fCallGetLastError ); + // + // construct the error message: + // + // it will be of the form: FuncName() failed for Object: + // + if( szFunctionName ) + { + mMsg = szFunctionName; + mMsg += _T(" failed"); + + if( szObjectName ) + { + mMsg += _T(" for "); + mMsg += szObjectName; + } + } + else if( szObjectName ) + { + mMsg = szObjectName; + } + else + { + mMsg = _T("Error"); + } + + if( fCallGetLastError ) + { + TSTRING strErr = strerror(errno); + + if( ! strErr.empty() ) + { + mMsg += _T(": "); + mMsg += strErr; + } + } +#endif // IS_UNIX +} + +// eof - unixexcept.cpp diff --git a/src/core/unixexcept.h b/src/core/unixexcept.h new file mode 100644 index 0000000..c1f1654 --- /dev/null +++ b/src/core/unixexcept.h @@ -0,0 +1,58 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// unixexcept.h +// +// unix api exception class +// +#ifndef __unixexcept_H +#define __unixexcept_H + +#ifndef __ERROR_H +#include "error.h" +#endif + +TSS_BEGIN_EXCEPTION( eUnix, eError ) + + eUnix( const TCHAR* functionName, const TCHAR* objectName, bool displayErrorNumber = true ); + // construct one of these to indicate a unix api failure. both functionName and + // objectName can be NULL. This method will construct a string to pass to eError + // that contains all of the above information plus whatever errno returns if the dusplayErrorNumber + // parameter is true. + + +TSS_END_EXCEPTION() + + + +#endif //__unixexcept_H + diff --git a/src/core/unixfsservices.cpp b/src/core/unixfsservices.cpp new file mode 100644 index 0000000..d74c6e9 --- /dev/null +++ b/src/core/unixfsservices.cpp @@ -0,0 +1,1163 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////// +// unixfsservices.cpp +// +// Implements cUnixFSServices class in unixfsservices.h +// + +#include "core/stdcore.h" +#include "core/corestrings.h" + +#if !IS_UNIX //encase this all in an ifdef so it won't cause compile errors +#error Must be unix for unixfsservices +#endif + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_MOUNT_H +# include +#endif +#ifdef HAVE_SYS_USTAT_H +# include +#endif +#ifdef HAVE_WCHAR_H +# include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "unixfsservices.h" + +// commented out definition of _TWNBITSMAJOR because we should use the +// makedev macro in sys/sysmacros.h for portability. +// except linux has the body of sysmacros.h commented out. why? +// -jeb 7/26/99 +// reduced to sys/statfs.h. Linux is OK and doesn't deserve +// special treatment. 20010317-PH +#ifdef HAVE_SYS_STATFS_H +# include +#endif //HAVE_SYS_STATFS_H + + + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +#define TW_SLASH _T('/') + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +using namespace std; + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +static bool util_FileIsExecutable( const TSTRING& ); +static bool util_PathFind( TSTRING& strFullPath, const TSTRING& strFilename ); +static void util_RemoveLastPathElement( TSTRING& strPath, TSTRING& strElem ); +static bool util_GetNextPathElement( const TSTRING& strPathC, TSTRING& strElem, int index ); +static void util_RemoveDuplicateSeps( TSTRING& strPath ); +static bool util_TrailingSep( TSTRING& str, bool fLeaveSep ); +static void util_RemoveTrailingSeps( TSTRING& str ); +template< typename T > static inline void util_ZeroMemory( T& obj ); + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + +cUnixFSServices::cUnixFSServices() +{} + +cUnixFSServices::~cUnixFSServices() +{} + +//========================================================================= +// *** VIRTUAL FUNCTION CODE *** +//========================================================================= + +/////////////////////////////////////////////////////////////////////////////// +// GetErrString +/////////////////////////////////////////////////////////////////////////////// +TSTRING cUnixFSServices::GetErrString() const +{ + TSTRING ret; + char* pErrorStr = strerror(errno); +#ifdef _UNICODE + wchar_t pBuf[1024]; + mbstowcs(pBuf, pErrorStr, 1024); + ret = pBuf; +#else + ret = pErrorStr; +#endif + return ret; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetHostID +/////////////////////////////////////////////////////////////////////////////// +void cUnixFSServices::GetHostID( TSTRING& name ) const +{ + TOSTRINGSTREAM ret; + + ret.setf(ios_base::hex, ios_base::basefield); +#ifdef HAVE_GETHOSTID + ret << gethostid(); +#else + ret << 999999; +#endif + +} + +// returns "/" for unix and "\\" for win32 +TCHAR cUnixFSServices::GetPathSeperator() const +{ + return '/'; +} + + +void cUnixFSServices::ReadDir(const TSTRING& strFilename, std::vector &v, bool bFullPaths) const throw(eFSServices) +{ + //Get all the filenames + DIR* dp; + dp = opendir( strFilename.c_str() ); + + if (dp == NULL) + { + throw eFSServicesGeneric( strFilename, iFSServices::GetInstance()->GetErrString() ); + return; + } + + struct dirent* d; + + while ((d = readdir(dp)) != NULL) + { + if ((strcmp(d->d_name, _T(".")) != 0) && (strcmp(d->d_name, _T("..")) != 0)) + { + if( bFullPaths ) + { + //Create the full pathname + TSTRING strNewName = strFilename; + + // get full path of dir entry + util_TrailingSep( strNewName, true ); + strNewName += d->d_name; + + // save full path name + v.push_back( strNewName ); + } + else + v.push_back( d->d_name ); + } + } + + //Close the directory + closedir( dp ); +} + +/* needs to and with S_IFMT, check EQUALITY with S_*, and return more types +cFSStatArgs::FileType cUnixFSServices::GetFileType(const cFCOName &filename) throw(eFSServices) +{ + cFSStatArgs stat; + Stat(filename, stat); + return stat.mFileType; +} +*/ + +void cUnixFSServices::GetCurrentDir( TSTRING& strCurDir ) const throw(eFSServices) +{ + TCHAR pathname[MAXPATHLEN]; + pathname[0] = '\0'; + TCHAR* ret = getcwd(pathname, sizeof(TCHAR)*MAXPATHLEN); + + if (ret == NULL) + throw eFSServicesGeneric( strCurDir, iFSServices::GetInstance()->GetErrString() ); + + strCurDir = pathname; +} + +void cUnixFSServices::ChangeDir( const TSTRING& strDir ) const throw(eFSServices) +{ + if( chdir( strDir.c_str() ) < 0 ) + throw eFSServicesGeneric( strDir, iFSServices::GetInstance()->GetErrString() ); +} + + +TSTRING& cUnixFSServices::MakeTempFilename( TSTRING& strName ) const throw(eFSServices) +{ + char* pchTempFileName; + char szTemplate[MAXPATHLEN]; + int fd; + +#ifdef _UNICODE + // convert template from wide character to multi-byte string + char mbBuf[MAXPATHLEN]; + wcstombs( mbBuf, strName.c_str(), strName.length() + 1 ); + strcpy( szTemplate, mbBuf ); +#else + strcpy( szTemplate, strName.c_str() ); +#endif + +#ifdef HAVE_MKSTEMP + // create temp filename and check to see if mkstemp failed + if ((fd = mkstemp( szTemplate )) == -1) { + throw eFSServicesGeneric( strName ); + } else { + close(fd); + } + pchTempFileName = szTemplate; +#else + fd = 0; + // create temp filename + pchTempFileName = mktemp( szTemplate ); + + //check to see if mktemp failed + if ( pchTempFileName == NULL || strlen(pchTempFileName) == 0) { + throw eFSServicesGeneric( strName ); + } +#endif + + // change name so that it has the XXXXXX part filled in +#ifdef _UNICODE + // convert name from multi-byte to wide character string + wchar_t wcsbuf[1024]; + mbstowcs( wcsbuf, pchTempFileName, strlen( pchTempFileName ) + 1 )); + strName = wcsbuf; +#else + strName = pchTempFileName; +#endif + + + // Linux creates the file!! Doh! + // So I'll always attempt to delete it -bam + FileDelete( strName ); + + return( strName ); +} + +void cUnixFSServices::Mkdir( const TSTRING& strName ) const throw ( eFSServices ) +{ + if( 0 != _tmkdir( strName.c_str(), 0777 ) ) + { + // if mkdir failed because the dir existed, that's OK + if( errno != EEXIST ) + throw eFSServicesGeneric( strName, iFSServices::GetInstance()->GetErrString() ); + } +} + +bool cUnixFSServices::Rmdir( const TSTRING& strName ) const +{ + if( 0 == rmdir( strName.c_str() ) ) + return true; + + return false; +} + +void cUnixFSServices::GetTempDirName( TSTRING& strName ) const throw(eFSServices) +{ + strName = mTempPath; +} + +void cUnixFSServices::SetTempDirName(TSTRING& tmpPath) { + + mTempPath = tmpPath; +} + + +void cUnixFSServices::Stat( const TSTRING& strName, cFSStatArgs &stat ) const throw(eFSServices) +{ + //local variable for obtaining info on file. + struct stat statbuf; + + int ret; + ret = lstat( strName.c_str(), &statbuf ); + + cDebug d( "cUnixFSServices::Stat" ); + d.TraceDetail( "Executing on file %s (result=%d)\n", strName.c_str(), ret ); + + if( ret < 0 ) + throw eFSServicesGeneric( strName, iFSServices::GetInstance()->GetErrString() ); + + // new stuff 7/17/99 - BAM + // if the file is not a device set rdev to zero by hand (most OSs will + // do this for us, but some don't) + if( ! S_ISBLK( statbuf.st_mode ) && ! S_ISCHR( statbuf.st_mode ) ) + { + // must zero memory instead of '= 0' since we don't know the + // actual type of the object -- could be a struct (requiring '= {0}' ) + util_ZeroMemory( statbuf.st_rdev ); + } + + //copy information returned by lstat call into the structure passed in + stat.gid = statbuf.st_gid; + stat.atime = statbuf.st_atime; + stat.ctime = statbuf.st_ctime; + stat.mtime = statbuf.st_mtime; + stat.dev = statbuf.st_dev; + stat.rdev = statbuf.st_rdev; + stat.ino = statbuf.st_ino; + stat.mode = statbuf.st_mode; + stat.nlink = statbuf.st_nlink; + stat.size = statbuf.st_size; + stat.uid = statbuf.st_uid; + stat.blksize = statbuf.st_blksize; + stat.blocks = statbuf.st_blocks; + + // set the file type + if(S_ISREG(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_FILE; + else if(S_ISDIR(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_DIR; + else if(S_ISLNK(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_SYMLINK; + else if(S_ISBLK(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_BLOCKDEV; + else if(S_ISCHR(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_CHARDEV; + else if(S_ISFIFO(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_FIFO; + else if(S_ISSOCK(statbuf.st_mode)) stat.mFileType = cFSStatArgs::TY_SOCK; + else stat.mFileType = cFSStatArgs::TY_INVALID; +} + +void cUnixFSServices::GetMachineName( TSTRING& strName ) const throw( eFSServices ) +{ + struct utsname namebuf; + if( uname( &namebuf ) == -1 ) + throw eFSServicesGeneric( strName ); + else + strName = namebuf.nodename; +} + +void cUnixFSServices::GetMachineNameFullyQualified( TSTRING& strName ) const +{ + char buf[256]; + if (gethostname(buf, 256) != 0) + { +#ifdef SOLARIS_NO_GETHOSTBYNAME + strName = buf; + return; +#else + struct hostent* ret; + ret = gethostbyname(buf); + + if (ret != NULL) + { + strName = ret->h_name; + return; + } +#endif + } + + try + { + cUnixFSServices::GetMachineName(strName); + } + catch(eFSServices&) + { + strName = TSS_GetString(cCore, core::STR_UNKNOWN); + } +} + +bool cUnixFSServices::FileDelete( const TSTRING& strName ) const +{ + return( 0 == remove( strName.c_str() ) ); +} + +bool cUnixFSServices::GetCurrentUserName( TSTRING& strName ) const +{ + bool fSuccess = false; + + uid_t uid = getuid(); + struct passwd* pp = getpwuid( uid ); + + if( pp ) + { + strName = pp->pw_name; + fSuccess = true; + } + else + strName = _T(""); + + return( fSuccess ); +} + + +// returns IP address in network byte order +bool cUnixFSServices::GetIPAddress( uint32& uiIPAddress ) +{ + bool fGotAddress = false; + cDebug d( _T("cUnixFSServices::GetIPAddress") ); + + struct utsname utsnameBuf; + if( EFAULT != uname( &utsnameBuf) ) + { + d.TraceDetail( "uname returned nodename: %s\n", utsnameBuf.nodename ); + + struct hostent* phostent = gethostbyname( utsnameBuf.nodename ); + + if( phostent ) + { + ASSERT( AF_INET == phostent->h_addrtype ); + ASSERT( sizeof(int32) == phostent->h_length ); + + if( phostent->h_length ) + { + if( phostent->h_addr_list[0] ) + { + int32* pAddress = reinterpret_cast( phostent->h_addr_list[0] ); + uiIPAddress = *pAddress; + fGotAddress = true; + } + else + d.TraceError( _T("phostent->h_addr_list[0] was zero") ); + } + else + d.TraceError( _T("phostent->h_length was zero") ); + } + else + d.TraceError( _T("gethostbyname failed") ); + } + else + d.TraceError( _T("uname failed") ); + + return( fGotAddress ); +} + +bool cUnixFSServices::IsCaseSensitive() const +{ + return true; +} + + +bool cUnixFSServices::GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const +{ + bool fSuccess = true; + struct stat statbuf; + + int ret = lstat(tstrFilename.c_str(), &statbuf); + if(ret < 0) + { + fSuccess = false; + } + + if( fSuccess ) + { + struct passwd* pp = getpwuid( statbuf.st_uid ); + //ASSERT( pp ); + // We shouldn't assert this, because it might be the case that a file + // is associated with some old user that no longer exists... we should + // not fail this case. Instead, the method will just return false per + // the test below. + if( pp == NULL ) + { + fSuccess = false; + } + else + tstrUser = pp->pw_name; + } + + return( fSuccess ); + +} + + +bool cUnixFSServices::GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tstrGroup ) const +{ + bool fSuccess = true; + struct stat statbuf; + + int ret = lstat(tstrFilename.c_str(), &statbuf); + if(ret < 0) + { + fSuccess = false; + } + + if( fSuccess ) + { + struct group* pg = getgrgid( statbuf.st_gid ); + //ASSERT( pg ); this assert stops everything in debug mode if we can't lookup a groupid + + if( pg == NULL ) + { + fSuccess = false; + tstrGroup = TSS_GetString(cCore, core::STR_UNKNOWN); + } + else + tstrGroup = pg->gr_name; + } + + return( fSuccess ); +} + +//////////////////////////////////////////////////////////////////////// +// Function name : cUnixFSServices::ConvertModeToString +// Description : takes a TSTRING and fills it with an "ls -l" representation +// of the object's permission bits ( e.g. "drwxr-x--x" ). +// +// Returns : void -- no errors are reported +// +// Argument : uint64 perm -- st_mode from "stat" +// Argument : TSTRING& tstrPerm -- converted permissions, ls -l style +// +void cUnixFSServices::ConvertModeToString( uint64 perm, TSTRING& tstrPerm ) const +{ + TCHAR szPerm[11]; //10 permission bits plus the NULL + _tcscpy( szPerm, _T("----------") ); + + ASSERT( sizeof(unsigned short) <= sizeof(uint32) ); + // We do this in case an "unsigned short" is ever larger than the + // value we are switching on, since the size of the mode parameter + // will be unsigned short (whatever that means, for the given platform...) + + // check file type + switch ((uint32)perm & S_IFMT) //some versions of Unix don't like to switch on + //64 bit values. + { + case S_IFDIR: + szPerm[0] = _T('d'); + break; + case S_IFCHR: + szPerm[0] = _T('c'); + break; + case S_IFBLK: + szPerm[0] = _T('b'); + break; + case S_IFIFO: + szPerm[0] = _T('p'); + break; + case S_IFLNK: + szPerm[0] = _T('l'); + break; + } + + // check owner read and write + if (perm & S_IREAD) + szPerm[1] = _T('r'); + if (perm & S_IWRITE) + szPerm[2] = _T('w'); + + // check owner execute + if (perm & S_ISUID && perm & S_IEXEC) + szPerm[3] = _T('s'); + else if (perm & S_IEXEC) + szPerm[3] = _T('x'); + else if (perm & S_ISUID) + szPerm[3] = _T('S'); + + // check group read and write + if (perm & S_IRGRP) + szPerm[4] = _T('r'); + if (perm & S_IWGRP) + szPerm[5] = _T('w'); + + // check group execute + if (perm & S_ISGID && perm & S_IXGRP) + szPerm[6] = _T('s'); + else if (perm & S_IXGRP) + szPerm[6] = _T('x'); + else if (perm & S_ISGID) + szPerm[6] = _T('l'); + + // check other read and write + if (perm & S_IROTH) + szPerm[7] = _T('r'); + if (perm & S_IWOTH) + szPerm[8] = _T('w'); + + // check other execute + if (perm & S_ISVTX && perm & S_IXOTH) + szPerm[9] = _T('t'); + else if (perm & S_IXOTH) + szPerm[9] = _T('x'); + else if (perm & S_ISVTX) + szPerm[9] = _T('T'); + + tstrPerm = szPerm; + + return; +} + +//////////////////////////////////////////////////////////////////////// +// Function name : cUnixFSServices::Rename +// Description : Rename a file. Overwrites newname if it exists.and overwrite is true +// +// Returns : false if failure, true on success +bool cUnixFSServices::Rename(const TSTRING& strOldName, const TSTRING& strNewName, bool overwrite) const +{ +#ifdef _UNICODE +#error UNICODE Rename not implemented +#endif + + // delete new file if overwriting + if ( overwrite ) + if ( access( strNewName.c_str(), F_OK ) == 0 && remove( strNewName.c_str() ) != 0 ) + return false; + + if ( rename( strOldName.c_str(), strNewName.c_str() ) == 0 ) + return true; + + // Note: errno will be set + return false; +} + + +bool cUnixFSServices::GetExecutableFilename( TSTRING& strFullPath, const TSTRING& strFilename ) const +{ + bool fGotName = false; + + if( strFilename.empty() ) + return false; + + // if there is a slash in the filename, it's absolute or relative to cwd + if( TSTRING::npos != strFilename.find( _T('/') ) ) + { + // if absolute path + if( strFilename[0] == _T('/') ) + { + strFullPath = strFilename; + fGotName = true; + } + else // is relative path; find path from cwd + { + fGotName = FullPath( strFullPath, strFilename ); + } + } + else // it's just a filename: should be found in path + { + fGotName = util_PathFind( strFullPath, strFilename ); + + TSTRING strFP; + if( fGotName && FullPath( strFP, strFullPath ) ) + strFullPath = strFP; + } + + return( fGotName ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function name : cUnixFSServices::FullPath +// Description : +// +// Return type : bool +// Argument : TSTRING& strFullPath +// Argument : const TSTRING& strRelPathC +// Argument : const TSTRING& pathRelFromC +// +// TODO -- is throwing an exception the more appropriate alternative to returning +// a bool? I think it is ... mdb +/////////////////////////////////////////////////////////////////////////////// +bool cUnixFSServices::FullPath( TSTRING& strFullPath, const TSTRING& strRelPathC, const TSTRING& pathRelFromC ) const +{ + // don't do anything with an empty path + if( strRelPathC.empty() ) + return false; + + TSTRING strRelPath = strRelPathC; // make non-const temp var + + // + // get base name (where strRelPath will be relative to), which will either be; + // 1. the root directory if strRelPath is an absolute path + // 2. pathRelFrom if it's not empty + // 3. otherwise ( not abs path AND no rel path ) the current working directory + // + + if( strRelPath[0] == TW_SLASH ) // if is absolute path + { + if( IsRoot( strRelPath ) ) // if it's root, don't monkey with it, just return it. + { + strFullPath = strRelPath; + return true; + } + else + { + strFullPath = _T(""); // push root, then add path elements from strRelPathC + // one by one (in while loop below) + } + } + else // is a relative path, so check pathRelFromC + { + if( pathRelFromC.empty() ) // if we're relative to CWD... + { + // + // get the current working directory + // + try + { + GetCurrentDir( strFullPath ); + util_TrailingSep( strFullPath, false ); + } + catch( eFSServices& ) + { + return false; + } + } + else // we're relative to a given dir + { + strFullPath = pathRelFromC; + util_RemoveDuplicateSeps( strFullPath ); + util_TrailingSep( strFullPath, false ); + } + } + + // + // start adding path elements from strRelPath to the base name + // ( which already has an absolute starting point. see above. ) + // + + TSTRING strElem; + int index = 0; + while( util_GetNextPathElement( strRelPath, strElem, index++ ) ) + { + if( 0 == strElem.compare( _T(".") ) ) + { + // ignore it + } + else if( 0 == strElem.compare( _T("..") ) ) + { + // go up a dir ( the function takes care of root dir case ) + TSTRING strDummy; + util_RemoveLastPathElement( strFullPath, strDummy ); + } + else // just a regular old path element + { + strFullPath += TW_SLASH; + strFullPath += strElem; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetStandardBackupExtension() +// +// Returns normal string to append to backup files for this os. +// (e.g. "~" for unix and ".bak" for winos) +/////////////////////////////////////////////////////////////////////////////// +TCHAR* cUnixFSServices::GetStandardBackupExtension() const +{ + return _T(".bak"); +} + + + // TODO: remove this function + // Matt theorized that this is no longer used - dmb Aug 23 1999 +/* +int cUnixFSServices::CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const +{ + // make sure perm is AT LEAST one of: O_RDWR, O_WRONLY + ASSERT( 0 != ( perm & ( O_RDWR | O_WRONLY ) ) ); + // make sure perm is ONLY composed of: O_RDWR, O_WRONLY + ASSERT( 0 == ( perm & ~( O_RDWR | O_WRONLY ) ) ); + // get rid of any unsupported bits caller may have supplied + perm &= ( O_RDWR | O_WRONLY ); + + // set flags + int oflags = perm | + O_CREAT | O_EXCL; // only create a new file -- error if it exists already + + // create file + int fh = _topen( szFilename, oflags, 0666 ); + if( fh >= 0 ) + { + // file was created. Now unlink it + if( 0 != unlink( szFilename ) ) + { + // we weren't able to unlink file, so close handle and fail + close( fh ); + fh = -1; + } + } + + return( fh ); +} +*/ + +void cUnixFSServices::Sleep( int nSeconds ) const +{ + sleep( nSeconds ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Function name : IsRoot +// Description : A root path is all '/'s +// +// Return type : bool +// Argument : const TSTRING& strPath +/////////////////////////////////////////////////////////////////////////////// +bool cUnixFSServices::IsRoot( const TSTRING& strPath ) const +{ + // and empty path is NOT the root path + if( strPath.empty() ) + return false; + + // check to see if all characters are a slash + for( TSTRING::const_iterator iter = strPath.begin(); iter != strPath.end(); iter++ ) + { + // if we've found a char that's not '/', then it's not the root path + if( *iter != TW_SLASH ) + return false; + } + + return true; +} + +//************************************************************************* +//************************************************************************* +// UTIL FUNCTION CODE +//************************************************************************* +//************************************************************************* + + +/////////////////////////////////////////////////////////////////////////////// +// Function name : util_PathFind +// Description : +// takes single-element executible filename and looks in path env var for it +// assumes path is colon-delimited string of directories. +// +// Return type : bool +// Argument : TSTRING& strFullPath +// Argument : const TSTRING& strFilename +/////////////////////////////////////////////////////////////////////////////// +bool util_PathFind( TSTRING& strFullPath, const TSTRING& strFilename ) +{ + bool fFoundFile = false; + + if( strFilename.empty() ) + return false; + + // + // get the path environment variable + // + TCHAR* pszPathVar = _tgetenv("PATH"); + if( pszPathVar != NULL ) + { + // + // cycle over characters in path looking for the ':' + // + TSTRING strCurPath; + TCHAR* pchTemp = pszPathVar; + bool fMorePaths = true; + do // while still more paths and haven't found file + { + // + // are we at the ':'? + // + if( *pchTemp && *pchTemp != _T(':') ) // if we're not at the end of the path + { + strCurPath += *pchTemp; + } + else // we have found the ':' + { + // + // expand current path into a fully qualified path + // if it's empty, use current directory + // + TSTRING strFP; + if( strCurPath.empty() ) + strCurPath = _T("."); + if( iFSServices::GetInstance()->FullPath( strFP, strCurPath ) ) + strCurPath = strFP; + + // + // put the file together with the path dir + // + TSTRING strFullName = strCurPath; + util_TrailingSep( strFullName, true ); + strFullName += strFilename; + + // + // the file must exist and be executable + // + if( util_FileIsExecutable( strFullName ) ) + { + strFullPath = strFullName; + fFoundFile = true; + } + else + strCurPath.erase(); // start over + } + + // + // keep searching if we're not at the end of the path string + // + + if( *pchTemp ) + pchTemp++; + else + fMorePaths = false; + } + while( !fFoundFile && fMorePaths ); + } + + return( fFoundFile ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function name : util_FileIsExecutable +// Description : file ( or file a link points to ) must be a regular +// file and executable by someone +// +// Return type : bool +// Argument : const TSTRING& strFile +/////////////////////////////////////////////////////////////////////////////// +bool util_FileIsExecutable( const TSTRING& strFile ) +{ + if( strFile.empty() ) + return false; + + struct stat s; + if( stat( strFile.c_str(), &s ) < 0 ) // this call handles links + return false; + + return( S_ISREG( s.st_mode ) && ( s.st_mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) ); // can someone execute it? +} + + +//////////////////////////////////////////////////////////////////////////////// +// Function name : util_RemoveDuplicateSeps +// Description : +// takes all adjacent slashes and replaces them with a single slash +// ///root//foo -> /root/foo +// rel//foo/// -> rel/foo/ +// +// Return type : void +// Argument : TSTRING& strPath +/////////////////////////////////////////////////////////////////////////////// +void util_RemoveDuplicateSeps( TSTRING& strPath ) +{ + bool fLastCharWasSep = false; + TSTRING::iterator iter = strPath.begin(); + while( iter != strPath.end() ) + { + bool fErasedChar = false; + // if we've found a char that's not '/', then it's not the root + if( *iter == TW_SLASH ) + { + // if this char is a duplicate sep, erase it + if( fLastCharWasSep ) + { + iter = strPath.erase( iter ); + fErasedChar = true; + } + + fLastCharWasSep = true; + } + else + { + fLastCharWasSep = false; + } + + // don't go past end of string (could happen with erase) + if( ! fErasedChar ) + iter++; + } +} + + +////////////////////////////////////////////////////////////////////////////////// +// Function name : util_RemoveLastPathElement +// Description : +// effectively pops off a path element from the end, except for the root dir, where it does nothing +// it removes any slashes before and after the element +// ///root//foo/ -> leaves "///root" ("foo" is strElem) +// ///root -> leaves "" ("root" is strElem) +// // -> leaves "" ("" is strElem) +// +// Return type : void +// Argument : TSTRING& strPath +// Argument : TSTRING& strElem +///////////////////////////////////////////////////////////////////////////////// +void util_RemoveLastPathElement( TSTRING& strPath, TSTRING& strElem ) +{ + + // remove all trailing separators + util_RemoveTrailingSeps( strPath ); + + // find the last separator + TSTRING::size_type lastSep = strPath.rfind( TW_SLASH ); + + // if separator was found, take all chars after it + if( lastSep != TSTRING::npos ) + { + strElem = strPath.substr( lastSep + 1 ); + strPath.resize( lastSep + 1 ); + } + else // no seps in name, take whole string + { + // last element + strElem = strPath; + strPath.erase(); + } + + // remove all trailing separators + util_RemoveTrailingSeps( strPath ); +} + + +//////////////////////////////////////////////////////////////////////////////////// +// Function name : util_GetNextPathElement +// Description : +// starting from the left side of the path string, returns the index'th path element +// returns true if the element exists, false if there aren't many elements +// +// index is ZERO BASED +// +// 2rd element of ABC/DEF/GH -> GH +// 1st element of //ABC/DEF/GH -> DEF +// +// Return type : bool : got path element? ( i.e. was there index path elements? ) +// Argument : const TSTRING& strPathC +// Argument : TSTRING& strElem +// Argument : int index +///////////////////////////////////////////////////////////////////////////////// +bool util_GetNextPathElement( const TSTRING& strPathC, TSTRING& strElem, int index ) +{ + + // don't do anything if root or empty + if( strPathC.empty() || iFSServices::GetInstance()->IsRoot( strPathC ) ) + return false; + + TSTRING strPath = strPathC; // writable local version + + bool fMoreSeps = true; + TSTRING::size_type firstSep, nextSep, nextNonSep; + firstSep = nextSep = nextNonSep = (TSTRING::size_type)-1; + for( int i = 0; i <= index && fMoreSeps; i++ ) + { + // go past leading separators + nextNonSep = strPath.find_first_not_of( TW_SLASH, nextSep + 1 ); + + if( nextNonSep != TSTRING::npos ) + { + // find index'th slash (start of index'th element) + nextSep = strPath.find( TW_SLASH, nextNonSep ); + + // if we're at the end and we haven't found the index'th element + // left, then tell the caller that there aren't that many elemnts + if( nextSep == TSTRING::npos && i < index ) + fMoreSeps = false; + + } + else + fMoreSeps = false; + } + + // get the element and remove it from the path + if( fMoreSeps ) + strElem = strPath.substr( nextNonSep, nextSep - nextNonSep ); + + return( fMoreSeps ); +} + +///////////////////////////////////////////////////////////////////////// +// Function name : util_TrailingSep +// Description : ensure that a path ( fLeaveSep ? "has" : "does not have" ) a trailing slash +// +// Return type : bool : was there a trailing slash? +// Argument : TSTRING& str +// Argument : bool fLeaveSep +///////////////////////////////////////////////////////////////////////////////// +bool util_TrailingSep( TSTRING& str, bool fLeaveSep ) +{ + bool fWasSep = false; + + // if there's a trailing sep + if( + ! str.empty() + && + str[ str.size() - 1 ] == TW_SLASH + ) + { + if( ! fLeaveSep ) + str.resize( str.size() - 1 ); + fWasSep = true; + } + else // else no trailing sep + { + if( fLeaveSep ) + str += TW_SLASH; + fWasSep = false; + } + + return( fWasSep ); +} + +///////////////////////////////////////////////////////////////////////// +// Function name : util_RemoveTrailingSeps +// Description : removes all trailing separators +// +// Return type : void +// Argument : TSTRING& str +///////////////////////////////////////////////////////////////////////////////// +void util_RemoveTrailingSeps( TSTRING& str ) +{ + while( util_TrailingSep( str, false ) ) + {} +} + +template< typename T > static inline void util_ZeroMemory( T& obj ) +{ + memset( &obj, 0, sizeof( obj ) ); +} + diff --git a/src/core/unixfsservices.h b/src/core/unixfsservices.h new file mode 100644 index 0000000..e2658e9 --- /dev/null +++ b/src/core/unixfsservices.h @@ -0,0 +1,206 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//////////////////////////////////////////////////////////////////////// +// unixfsservices.h +// +// cUnixFSServices implements iFSServices, which abstacts out all +// system dependent filesystem calls. + +#ifndef __UNIXFSSERVICES_H +#define __UNIXFSSERVICES_H + +#if !IS_UNIX +#error unixfsservices.h should only be included for instantiating cUnixFSServices objects. If you just want to use iFSServices methods, include fsservices.h. Same goes for cWin32FSServices. +#endif + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __FSSERVICES_H +#include "core/fsservices.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//Set up in constructor. Stores pertinent information about the filesystem +//serviced by each instantiation. + +struct UnixSysInfo +{ + uint32 maxcomplen; + //max name length of a file on filesystem + uint32 fsflags; + //bitmask of flags + TSTRING fsname; + //The filesystem basename + uint32 fsid; + //unique indentifier for the filesystem +}; + +class cUnixFSServices : public iFSServices +{ + /////////////////////////////////////////////////////////////// + // ENUMS + /////////////////////////////////////////////////////////////// + + //////////////////////////////////////// + // file system types + //////////////////////////////////////// + enum FSType + { + FS_UFS = 0, + FS_NFS, + FS_HSFS, + FS_PCFS + }; + + /////////////////////////////////////////////////////////////// + // MEMBER FUNCTIONS + /////////////////////////////////////////////////////////////// + public: + cUnixFSServices(); + virtual ~cUnixFSServices(); + + + //////////////////////////////////////// + // platform specific functions + //////////////////////////////////////// + virtual bool IsCaseSensitive() const; + // returns true if the file system is case sensitive + virtual TCHAR* GetStandardBackupExtension() const; + // returns normal string to append to backup files for this os. + // (e.g. "~" for unix and ".bak" for winos) + virtual TCHAR GetPathSeperator() const; + + //////////////////////////////////////// + // process functions + //////////////////////////////////////// + virtual void Sleep( int nSeconds ) const; + // makes the current process sleep for the specified number of seconds + + //////////////////////////////////////// + // major filesystem functions + //////////////////////////////////////// + virtual void Stat( const TSTRING& strFileName, cFSStatArgs& pStat ) const throw( eFSServices ); + // fills out the cFSStatArgs structure with the stat info for the named file + + virtual void GetTempDirName( TSTRING& strName ) const throw( eFSServices ); + // makes directory if it doesn't exist already. Dirname will end with a delimiter ( '/' ) + + virtual void SetTempDirName(TSTRING& tmpName); + // set the default dir name which GetTempDirName will use... + + virtual TSTRING& MakeTempFilename( TSTRING& strName ) const throw( eFSServices ); + // create temporary file + // strName must have the form ("baseXXXXXX"), where the X's are replaced with + // characters to make it a unique file. There must be at least 6 Xs. + + // TODO: remove this function + // Matt theorized that this is no longer used - dmb Aug 23 1999 + //virtual int CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const; + + + //////////////////////////////////////// + // minor filesystem functions + //////////////////////////////////////// + virtual void GetHostID( TSTRING& name ) const; + + virtual void GetMachineName( TSTRING& name) const throw(eFSServices); + + virtual void GetMachineNameFullyQualified( TSTRING& name ) const; + + virtual bool GetCurrentUserName( TSTRING& tstrName ) const; + + virtual bool GetIPAddress( uint32& uiIPAddress ); + + + //////////////////////////////////////// + // directory specific functions + //////////////////////////////////////// + virtual void ReadDir( const TSTRING& strName, std::vector &vDirContents, bool bFullPaths = true ) const throw( eFSServices ); + // puts the contents of the specified directory, except for . and .., into the supplied vector. + virtual void GetCurrentDir( TSTRING& strCurDir ) const throw( eFSServices ); + // returns the current working directory + virtual void ChangeDir( const TSTRING& strName ) const throw( eFSServices ); + // sets the current working directory + virtual void Mkdir( const TSTRING& strName ) const throw( eFSServices ); + + virtual bool Rmdir( const TSTRING& strName ) const; + + + //////////////////////////////////////// + // file specific functions + //////////////////////////////////////// + virtual bool FileDelete( const TSTRING& name ) const; + + + //////////////////////////////////////// + // directory and file functions + //////////////////////////////////////// + virtual bool Rename( const TSTRING& strOldName, const TSTRING& strNewName, bool fOverWrite = true ) const; + // rename a file + virtual bool GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const; + + virtual bool GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tstrGroup ) const; + + + //////////////////////////////////////// + // miscellaneous utility functions + //////////////////////////////////////// + virtual void ConvertModeToString( uint64 perm, TSTRING& tstrPerm ) const; + // takes a int64 permission (from stat) and changes it to look like UNIX's 'ls -l' (e.g. drwxrwxrwx) + virtual bool FullPath( TSTRING& fullPath, const TSTRING& relPath, const TSTRING& pathRelFrom = _T("") ) const; + // converts relPath into a fully qualified path, storing it in FullPath. If this + // fails, false is returned. if the path to which relPath is relative is not CWD, put it in pathRelFrom. + virtual bool GetExecutableFilename( TSTRING& strFullPath, const TSTRING& strFilename ) const; + // get the path to the current executable file + virtual bool IsRoot( const TSTRING& strPath ) const; + // returns true if strPath is all '/'s + + //////////////////////////////////////// + // error functions + //////////////////////////////////////// + virtual TSTRING GetErrString() const; + + private: + UnixSysInfo info; + //struct stores pertinent system info. to be used by member functions + + TSTRING mTempPath; + +}; + +#endif //__UNIXFSSERVICES_H + diff --git a/src/core/unixfsservices_t.cpp b/src/core/unixfsservices_t.cpp new file mode 100644 index 0000000..15966c6 --- /dev/null +++ b/src/core/unixfsservices_t.cpp @@ -0,0 +1,208 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// unixfsservices_t.cpp: Tests cUnixFSServices + +//#include +#include "core/stdcore.h" +#include "unixfsservices.h" +#include +#include "core/archive.h" +#include "fco/fconame.h" + +#if IS_UNIX + +#ifndef __TEST_H +#include "test/test.h" +#endif + +using namespace std; + +//Tests the functions that are currently implemented in win32fsservices. +void TestUnixFSServices() +{ + cDebug d("TestUnixFSServices"); + // d.RemoveOutTarget(cDebug::OUT_STDOUT); + + try + { + iFSServices* pFSServices = iFSServices::GetInstance(); + + // working primarily with the temp dir. + cFCOName name(_T("/tmp")); // dies here + + // Check to make sure /tmp is a dir + //TEST(pFSServices->GetFileType(name) == cFSStatArgs::TY_DIR); + + // get directory contents (test readdir) + std::vector v; + pFSServices->ReadDir(name.AsString(), v); + + { + d.TraceDebug("name: %d entries\n", v.size()); + + std::vector ::iterator p; + int n = 0; + for (p = v.begin(); p != v.end(); p++) { + d.TraceDetail(" %s\n", p->c_str()); + n++; + } + + TEST(n == v.size()); + } + + //Test the Stat method + cFSStatArgs stat; + + //TO DO: use archive to create this file + TSTRING testfile = "/tmp/tmp.tmp"; + cFileArchive filearch; + filearch.OpenReadWrite(testfile.c_str()); + filearch.Seek(0, cBidirArchive::BEGINNING); + filearch.WriteString(_T("This is a test")); + filearch.Close(); + + pFSServices->Stat(testfile, stat); + + //print out the information returned by Stat + d.TraceDetail("Information returned by Stat: \n"); + d.TraceDetail("Group ID : %-5d \n", stat.gid); + //d.TraceDetail("Last access time: %d \n", stat.atime); + d.TraceDetail("Last inode change: %d \n", stat.ctime); + d.TraceDetail("Last modified: %d \n", stat.mtime); + d.TraceDetail("Major/minor device nums: %d \n", stat.dev); + d.TraceDetail("Inode # of file : %d \n", stat.ino); + d.TraceDetail("Mode bits: %d \n", stat.mode); + d.TraceDetail("Num links: %d \n", stat.nlink); + d.TraceDetail("Major/minor dev if special: %d \n", stat.rdev); + d.TraceDetail("File size: %d \n", stat.size); + d.TraceDetail("User ID: %d \n", stat.uid); + + //Test GetCurrentDir: + TSTRING currpath; + pFSServices->GetCurrentDir(currpath); + d.TraceDetail("GetCurrentDir returned %s\n", currpath.c_str()); + //TEST(currpath == _T("~")); + //they should both be ~!! + + //Test MakeTempFilename + TSTRING _template(_T("twtempXXXXXX")); + pFSServices->MakeTempFilename(_template); + d.TraceDetail("Testing MakeTempFilename: \n"); + d.TraceDetail("%s \n", _template.c_str() ); + + //Test ChangeDir + d.TraceDetail("Testing ChangeDir: (should be /usr)\n"); + TSTRING newdir(_T("/usr")); + pFSServices->ChangeDir(newdir); + pFSServices->GetCurrentDir(currpath); + d.TraceDetail("%s \n", currpath.c_str() ); + //Did we get there?? + + //Test Mkdir: + d.TraceDetail("Testing Mkdir: \n"); + TSTRING makedir(_T("/tmp/tw_mkdir")); + pFSServices->Mkdir(makedir); // throws on error + + //Test Rmdir + d.TraceDetail("Testing Rmdir:\n"); + TEST( pFSServices->Rmdir(makedir) ); + + // Test GetMachineName + d.TraceDetail("Testing GetMachineName:\n"); + TSTRING uname; + pFSServices->GetMachineName(uname); + d.TraceDetail("GetMachineName returned: %s\n", uname.c_str()); + + // Test GetHostID + d.TraceDetail("Testing GetHostID:\n"); + TSTRING hostid; + pFSServices->GetHostID(hostid); + d.TraceDetail("GetHostID returned: %s\n", hostid.c_str()); + + // Test GetCurrentUserName + d.TraceDetail("Testing GetCurrentUserName:\n"); + TSTRING username; + TEST( pFSServices->GetCurrentUserName(username) ); + d.TraceDetail("GetCurrentUserName returned: %s\n", username.c_str()); + + // Test GetIPAddress + d.TraceDetail("Testing GetIPAddress:\n"); + uint32 *ipaddr; + TEST( pFSServices->GetIPAddress( *ipaddr ) ); + d.TraceDetail("GetIPAddress returned: %d\n", ipaddr); + + // test GetExecutableFilename + d.TraceDetail("Testing GetExecutableFilename: \n"); + TSTRING filename = _T("sh"); + TSTRING fullpath = _T("/bin/"); + TEST(pFSServices->GetExecutableFilename(fullpath, filename)); + filename = _T("/bin/sh"); + TEST(pFSServices->GetExecutableFilename(fullpath, filename)); + + // test Rename + d.TraceDetail("Testing Rename:\n"); + TSTRING newtestfile = _T("/tmp/new.tmp"); + TEST( pFSServices->Rename( testfile, newtestfile ) ); + + // test GetOwnerForFile + d.TraceDetail("Testing GetOwnerForFile:\n"); + TSTRING ownername; + TEST( pFSServices->GetOwnerForFile( newtestfile, ownername ) ); + d.TraceDetail("GetOwnerForFile returned owner %s.\n", ownername.c_str()); + + // test GetGroupForFile + d.TraceDetail("Testing GetGroupForFile:\n"); + TSTRING groupname; + TEST( pFSServices->GetGroupForFile( newtestfile, groupname ) ); + d.TraceDetail("GetGroupForFile returned group %s.\n", groupname.c_str()); + + // test FileDelete + d.TraceDetail("Testing FileDelete:\n"); + TEST( pFSServices->FileDelete( newtestfile ) ); + + + + }//end try block + catch (eError& e) + { + d.TraceError("Exception caught: %s\n", e.GetMsg()); + } + +} +#endif // IS_UNIX + + + + + + + diff --git a/src/core/upperbound.h b/src/core/upperbound.h new file mode 100644 index 0000000..52d9b05 --- /dev/null +++ b/src/core/upperbound.h @@ -0,0 +1,92 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// upperbound.h +// + +#ifndef __UPPERBOUND_H +#define __UPPERBOUND_H + +///////////////////////////////////////////////////////////////////////////////////////////// +// Function name: template< class FwdIterT, class CmpObjT, class CmpFuncT > +// UpperBound +// +// Description : same as std::upper_bound except it allows 'less' to take +// parameters of dissimilar types. Therefore, *FwdIter need not be +// the same type as CmpObjT. Uses a binary search algorithm. +// +// Return type : FwdIterT : First element in the sequence [first, last) +// that is equal to or greater than 'obj' or +// 'last' if there is no such element. +// +// Argument : FwdIterT first : First element in sequence. +// Argument : FwdIterT last : Last element in sequence. +// Argument : const CmpObjT& obj: Object for which to search for upper bound. +// Argument : CmpFuncT less : Comparison function. Must return as 'std::less'. +// Will be called as: 'bool less( *FwdIterT, CmpObjT )'. +///////////////////////////////////////////////////////////////////////////////////////////// +template< class FwdIterT, class CmpObjT, class CmpFuncT > FwdIterT UpperBound( FwdIterT first, FwdIterT last, const CmpObjT& obj, CmpFuncT less ) +{ + // count elements in set + int nElemsInSet = 0; + FwdIterT iCur = first; + for (; iCur != last; ++iCur ) + ++nElemsInSet; + + iCur = first; + + while( 0 < nElemsInSet ) + { + // go to halfway point + int iHalfWay = nElemsInSet/2; + FwdIterT iTemp = iCur; + for( int j = 0; j < iHalfWay; j++ ) + iTemp++; + + if( less( *iTemp, obj ) ) + { + // start next search set at next elem with half of the last search set's elements + iCur = ++iTemp; + nElemsInSet -= iHalfWay + 1; // already searched ( iHalfway + 1 ) elems + } + else + { + // start next search set beginning with half of the last search set's elements + nElemsInSet = iHalfWay; + } + } + + return iCur; +} + +#endif // __UPPERBOUND_H + diff --git a/src/core/usernotify.cpp b/src/core/usernotify.cpp new file mode 100644 index 0000000..5d26539 --- /dev/null +++ b/src/core/usernotify.cpp @@ -0,0 +1,112 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// usernotify.cpp +#include "stdcore.h" +#include "usernotify.h" + +#if defined(__OpenBSD__) /* OpenBSD's varargs seems wacky */ +# undef va_start +# ifdef __GNUC__ +# define va_start(ap, last) \ + ((ap) = (va_list)__builtin_next_arg(last)) +# else +# define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) +# endif +#endif /* __OpenBSD__ */ + +iUserNotify* iUserNotify::mpInstance = 0; + +iUserNotify::iUserNotify(int verboseLevel) : + mVerboseLevel(verboseLevel) +{ +} + +iUserNotify::~iUserNotify() +{ +} + +void iUserNotify::SetVerboseLevel(int level) +{ + mVerboseLevel = level; +} + +int iUserNotify::GetVerboseLevel() const +{ + return mVerboseLevel; +} + +/////////////////////////////////////////////////////////////////////////////// +// NotifySilent +/////////////////////////////////////////////////////////////////////////////// +void iUserNotify::NotifySilent( const TCHAR* format, ... ) +{ + va_list args; + va_start(args, format); + HandleNotify( V_SILENT, format, args ); + va_end(args); +} + +/////////////////////////////////////////////////////////////////////////////// +// NotifyNormal +/////////////////////////////////////////////////////////////////////////////// +void iUserNotify::NotifyNormal( const TCHAR* format, ... ) +{ + va_list args; + va_start(args, format); + HandleNotify( V_NORMAL, format, args ); + va_end(args); +} + +/////////////////////////////////////////////////////////////////////////////// +// NotifyVerbose +/////////////////////////////////////////////////////////////////////////////// +void iUserNotify::NotifyVerbose( const TCHAR* format, ... ) +{ + va_list args; + va_start(args, format); + HandleNotify( V_VERBOSE, format, args ); + va_end(args); +} + +/////////////////////////////////////////////////////////////////////////////// +// Notify +/////////////////////////////////////////////////////////////////////////////// +void iUserNotify::Notify(int verboseLevel, const TCHAR* format, ...) +{ + va_list args; + va_start(args, format); + HandleNotify( verboseLevel, format, args ); + va_end(args); +} + + diff --git a/src/core/usernotify.h b/src/core/usernotify.h new file mode 100644 index 0000000..4fd5066 --- /dev/null +++ b/src/core/usernotify.h @@ -0,0 +1,132 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// usernotify.h +// +// iUserNotify -- interface for notifying the user of events +#ifndef __USERNOTIFY_H +#define __USERNOTIFY_H + +#ifndef __DEBUG_H +#include "debug.h" +#endif +#ifndef va_start +#include +#endif + +class iUserNotify +{ +public: + // singleton interface; caller is responsible for deleting pointer; + static iUserNotify* GetInstance(); + static void SetInstance(iUserNotify* pInst); + + virtual void Notify(int verboseLevel, const TCHAR* format, ...) ; + // notify the user that an event has occured. The outcome of this operation is + // dependant on the type of object that is implementing this interface (for example, + // a console application would want an iUserNotify that prints things to stdout) + // If the current verbosity level is less than verboseLevel, nothing will happen. + // All output should be sent through the cDisplayEncoder beforehand + // TODO:BAM -- enforce this somehow? + + virtual void SetVerboseLevel(int level); + virtual int GetVerboseLevel() const; + // get/set the current verbosity level. Notify()s that occur whose verbosity level + // is greater than the current level will not be processed. + + // a convenience enumeration; no one is bound by law to use these + enum VerboseLevel + { + V_SILENT = 0, + V_NORMAL = 1, + V_VERBOSE = 2 + }; + // + // convenience methods for notifying at these three levels... + // + void NotifySilent ( const TCHAR* format, ... ); + void NotifyNormal ( const TCHAR* format, ... ); + void NotifyVerbose ( const TCHAR* format, ... ); + + + iUserNotify(int verboseLevel = 0); + virtual ~iUserNotify(); +protected: + virtual void HandleNotify( int level, const TCHAR* format, va_list& args ) = 0; + // this is implemented in derived classes to implement the specific type of + // notification desired + + int mVerboseLevel; +private: + static iUserNotify* mpInstance; +}; + + +//----------------------------------------------------------------------------- +// notify macros +// +// use these as an alternative to iUserNotify::GetInstance()->Notify( XXX ) +// becuase the call will not be made if it is not the appropriate verbosity +// level. This is useful when you don't want the "..." part of Notify() to be +// evaluated (for example, if it is an expensive operation like cFCOName::AsString() +// +//----------------------------------------------------------------------------- + +#define TW_NOTIFY_SILENT\ + if( iUserNotify::GetInstance()->GetVerboseLevel() >= iUserNotify::V_SILENT )\ + iUserNotify::GetInstance()->NotifySilent + +#define TW_NOTIFY_NORMAL\ + if( iUserNotify::GetInstance()->GetVerboseLevel() >= iUserNotify::V_NORMAL )\ + iUserNotify::GetInstance()->NotifyNormal + +#define TW_NOTIFY_VERBOSE\ + if( iUserNotify::GetInstance()->GetVerboseLevel() >= iUserNotify::V_VERBOSE )\ + iUserNotify::GetInstance()->NotifyVerbose + +//############################################################################# +// inline implementation +//############################################################################# +inline iUserNotify* iUserNotify::GetInstance() +{ + ASSERT(mpInstance != 0); + return mpInstance; +} + +inline void iUserNotify::SetInstance(iUserNotify* pInst) +{ + mpInstance = pInst; +} + + +#endif //__USERNOTIFY_H + diff --git a/src/core/usernotifystdout.cpp b/src/core/usernotifystdout.cpp new file mode 100644 index 0000000..751feaf --- /dev/null +++ b/src/core/usernotifystdout.cpp @@ -0,0 +1,56 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// usernotifystdout.cpp +#include "stdcore.h" +#include "usernotifystdout.h" + +/////////////////////////////////////////////////////////////////////////////// +// HandleNotify +/////////////////////////////////////////////////////////////////////////////// +void cUserNotifyStdout::HandleNotify( int level, const TCHAR* format, va_list& args ) +{ + if(GetVerboseLevel() < level) + return; + + // all verbose output now goes to stderr + if(level < iUserNotify::V_VERBOSE) + { + _vtprintf(format, args); + fflush( stdout ); + } + else + { + _vftprintf(stderr, format, args); + fflush( stderr ); + } +} + diff --git a/src/core/usernotifystdout.h b/src/core/usernotifystdout.h new file mode 100644 index 0000000..3fb0a5f --- /dev/null +++ b/src/core/usernotifystdout.h @@ -0,0 +1,53 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// usernotifystdout.h +// +// cUserNotifyStdout -- implements iUserNotify by printing to stdout +#ifndef __USERNOTIFYSTDOUT_H +#define __USERNOTIFYSTDOUT_H + +#ifndef __USERNOTIFY_H +#include "usernotify.h" +#endif + +class cUserNotifyStdout : public iUserNotify +{ +public: + virtual void HandleNotify( int level, const TCHAR* format, va_list& args ) ; + // formats the string and sends it to stdout + // NOTE -- a little tripwire specific hack has been applied that makes all output + // at or above iUserNotify::V_VERBOSE go to stderr instead of stdout +}; + +#endif /* __USERNOTIFYSTDOUT_H */ + diff --git a/src/core/usernotifystdout_t.cpp b/src/core/usernotifystdout_t.cpp new file mode 100644 index 0000000..f4a5187 --- /dev/null +++ b/src/core/usernotifystdout_t.cpp @@ -0,0 +1,45 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// usernotifystdout_t.cpp + +#include "stdcore.h" +#include "usernotifystdout.h" +#include "debug.h" +#include "test/test.h" + +void TestUserNotifyStdout() +{ + cDebug d("TestUserNotifyStdout"); + d.TraceError("Implement this!\n"); + TEST(false); +} diff --git a/src/core/userstring.cpp b/src/core/userstring.cpp new file mode 100644 index 0000000..f94d8af --- /dev/null +++ b/src/core/userstring.cpp @@ -0,0 +1,37 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// userstring.cpp +#include "stdcore.h" +#include "userstring.h" + +iUserString* iUserString::mpInstance; + diff --git a/src/core/userstring.h b/src/core/userstring.h new file mode 100644 index 0000000..61ada7f --- /dev/null +++ b/src/core/userstring.h @@ -0,0 +1,134 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// UserString.h -- A single point of access for all strings that will be +// displayed to the end user. This implementation is intended to ease +// any future localization efforts. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __USERSTRING_H +#define __USERSTRING_H + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +#ifndef _MAP_ +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class iUserString -- Abstract interface for retrieving User Strings +/////////////////////////////////////////////////////////////////////////////// + +class iUserString +{ +public: + virtual ~iUserString() {} + + struct tStringPair + { + int id; + TCHAR* string; + }; + + // Select between the different localized string sets + // for this product. Returns false if string not defined. + virtual bool SelectStringSet(int setID) = 0; + + // Get the string from the localized string set + virtual const TCHAR* GetString(int stringID) const = 0; + + // Clear all strings in specified string set + virtual void ClearStringSet(int id) = 0; + + // Add an array of string pairs to a string set. The pair array passed in + // should terminate with an id of -1. If this string set contains string IDs + // that already exist in the string set, they will "overwrite" the + // the previous strings. + // Note: We store only pointers to the string pairs so they must remain + // around for as long as this class uses them. A static array defined at + // compile time is perfect for this. + virtual void AddStringSet(int setID, const tStringPair* pPairArray) = 0; + + // Add a single string. The above rules apply. + virtual void AddString(int setID, int stringID, TCHAR* string) = 0; + + // singleton manipulation + static iUserString* GetInstance(); + static void SetInstance(iUserString* pInst); +private: + static iUserString* mpInstance; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Macros useful for building UserString tables. +/////////////////////////////////////////////////////////////////////////////// + +/* +Example Use: + + static struct iUserString::tStringPair englishStrings[] = + { + USERSTRING(STR_HELLO_WORLD, "Hello World\n") + USERSTRING(STR_OUT_OF_MEM, "Fatal Error: Out of memory.\n") + USERSTRING_END() + }; + + pUSMB->AddStringSet(LANG_USENGLISH, englishStrings); +*/ + +#define USERSTRING(id, str) { (id), _T(str) }, + +#define USERSTRING_END() { -1, _T("") } + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// inline implementation +/////////////////////////////////////////////////////////////////////////////////////////////////// +inline iUserString* iUserString::GetInstance() +{ + ASSERT(mpInstance); + + return mpInstance; +} + +inline void iUserString::SetInstance(iUserString* pInst) +{ + mpInstance = pInst; +} + + +#ifdef _MSC_VER +//#pragma warning(default:4786) +#endif /* _MSC_VER */ + +#endif // __USERSTRING_H diff --git a/src/core/userstringmem.cpp b/src/core/userstringmem.cpp new file mode 100644 index 0000000..29adf12 --- /dev/null +++ b/src/core/userstringmem.cpp @@ -0,0 +1,170 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdcore.h" +#include "userstringmem.h" +#include "debug.h" + +/////////////////////////////////////////////////////////////////////////////// +// class cUserStringMemBased -- A implementation where the various string +// sets are compiled into the executable (as opposed to loading them +// from an external file at run time). At startup someone needs to +// construct a cUserStringMemBased and set any valid string sets. +/////////////////////////////////////////////////////////////////////////////// + +cUserStringMemBased::cUserStringMemBased() +{ + mCurrentStringSet = 0; + mStringSets.clear(); +} + +cUserStringMemBased::~cUserStringMemBased() +{ + while (!mStringSets.empty()) + { + mStringSets.erase(mStringSets.begin()); + } +} + +// the abstract interface +bool cUserStringMemBased::SelectStringSet(int setID) +{ + if (mStringSets.find(setID) == mStringSets.end()) + return false; + + mCurrentStringSet = setID; + return true; +} + +const TCHAR* cUserStringMemBased::GetString(int stringID) const +{ + std::map::const_iterator setItr; + + setItr = mStringSets.find(mCurrentStringSet); + if (setItr == mStringSets.end()) + { + // mCurrentStringSet is invallid + ASSERT(false); + return _T(""); + } + + StringSet::const_iterator stringItr; + + ASSERT(setItr->second); + stringItr = setItr->second->find(stringID); + if (stringItr == setItr->second->end()) + { + // string not found + ASSERT(false); + return _T(""); + } + + return stringItr->second; +} + +// Clear all strings in specified string set +void cUserStringMemBased::ClearStringSet(int id) +{ + std::map::iterator setItr; + + setItr = mStringSets.find(id); + if (setItr == mStringSets.end()) + { + return; + } + + delete setItr->second; + mStringSets.erase(setItr); +} + +// Add an array of string pairs to a string set. The pair array passed in +// should terminate with an id of -1. If this string set contains string IDs +// that already exist in the string set, they will "overwrite" the +// the previous strings. +// Note: We store only pointers to the string pairs so they must remain +// around for as long as this class uses them. A static array defined at +// compile time is perfect for this. +void cUserStringMemBased::AddStringSet(int setID, const iUserString::tStringPair* pPairArray) +{ + std::map::const_iterator setItr; + + setItr = mStringSets.find(setID); + if (setItr == mStringSets.end()) + { + // first time we have seen this setID + setItr = mStringSets.insert(mStringSets.begin(), std::pair(setID, new StringSet)); + } + + ASSERT(pPairArray); + while (pPairArray->id >= 0) + { + StringSet::iterator stringItr; + + ASSERT(setItr->second); + stringItr = setItr->second->find(pPairArray->id); + if (stringItr != setItr->second->end()) + { + // Already a string of for this ID, + // so lets replace it! + setItr->second->erase(stringItr); + } + + setItr->second->insert(std::pair(pPairArray->id, pPairArray->string)); + + pPairArray++; + } +} + +void cUserStringMemBased::AddString(int setID, int stringID, TCHAR* string) +{ + std::map::const_iterator setItr; + + setItr = mStringSets.find(setID); + if (setItr == mStringSets.end()) + { + // first time we have seen this setID + setItr = mStringSets.insert(mStringSets.begin(), std::pair(setID, new StringSet)); + } + + StringSet::iterator stringItr; + + ASSERT(setItr->second); + stringItr = setItr->second->find(stringID); + if (stringItr != setItr->second->end()) + { + // Already a string of for this ID, + // so lets replace it! + setItr->second->erase(stringItr); + } + + setItr->second->insert(std::pair(stringID, string)); +} + diff --git a/src/core/userstringmem.h b/src/core/userstringmem.h new file mode 100644 index 0000000..c7130c3 --- /dev/null +++ b/src/core/userstringmem.h @@ -0,0 +1,91 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// UserString.h -- A single point of access for all strings that will be +// displayed to the end user. This implementation is intended to ease +// any future localization efforts. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __DEBUG_H +#include "debug.h" +#endif + +#ifndef __USERSTRINGMEM_H +#define __USERSTRINGMEM_H + +#ifdef _MSC_VER +#pragma warning(disable:4786) /* disable unwanted C++ /W4 warning */ +/* #pragma warning(default:4786) */ /* use this to reenable, if necessary */ +#endif /* _MSC_VER */ + +#ifndef __USERSTRING_H +#include "userstring.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cUserStringMemBased -- A implementation where the various string +// sets are compiled into the executable (as opposed to loading them +// from an external file at run time). At startup someone needs to +// construct a cUserStringMemBased and set any valid string sets. +/////////////////////////////////////////////////////////////////////////////// + +// Note: If we ever want to use an external text file for User Strings, we +// could derive another class from iUserString called cUserStringFileBased +// that retrieved strings from files. + +class cUserStringMemBased : public iUserString +{ +public: + cUserStringMemBased(); + ~cUserStringMemBased(); + + // the abstract interface + virtual bool SelectStringSet (int setID); + virtual const TCHAR* GetString (int stringID) const; + virtual void ClearStringSet (int id); + virtual void AddStringSet (int setID, const iUserString::tStringPair* pPairArray); + virtual void AddString (int setID, int stringID, TCHAR* string); + +private: + typedef std::map StringSet; + + int mCurrentStringSet; + std::map mStringSets; +}; + + +#ifdef _MSC_VER +//#pragma warning(default:4786) +#endif /* _MSC_VER */ + +#endif // __USERSTRINGMEM_H + diff --git a/src/core/utf8.cpp b/src/core/utf8.cpp new file mode 100644 index 0000000..953f7e4 --- /dev/null +++ b/src/core/utf8.cpp @@ -0,0 +1,152 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// utf8.h +// +#include "stdcore.h" +#include "utf8.h" // Required Deps +#include "tchar.h" +//#include "integ/tss.integ.strings.h" +//#include "integ/tss.integ.strings.inl" + +#ifdef _UNICODE + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// CLASS UTF8: Member Definitions +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// NOTES: utf8 uses "lazy evaluation" so that members are only allocated +// if they are used. However, once they are evaluated, the evaluation results +// will be saved so that values may henceforth simply be returned. This +// scheme gives the best time vs. space performance possible as the complexity +// of each operation is at most, linear. + + +const char* cUTF8::str() const THROW(std::bad_alloc) // UTF8: Get as Narrow UTF8 +{ + if ( mUTF8Str == 0 ) // If mUTF8Str is NULL mUnicodeStr can't be + mUTF8Str = cUTF8::allocate( mUnicodeStr ); + + return mUTF8Str; +} + +const wchar_t* cUTF8::ustr() const THROW(std::bad_alloc) // UTF8: Get as UNICODE NTWCS +{ + if ( mUnicodeStr == 0 ) + mUnicodeStr = cUTF8::allocate( mUTF8Str ); // If mUnicodeStr is NULL mUTF8WideStr can't be + + return mUnicodeStr; +} + +const wchar_t* cUTF8::wstr() const THROW(std::bad_alloc) // UTF8: Get as Wide UTF8 +{ + if ( mUTF8WideStr == 0 ) + { + size_t N = ::strlen( str() ); // WARNING: Get strlen NOT mbcslen!!! + mUTF8WideStr = new wchar_t[ N + 1 ]; // This may throw bad_alloc to client + + for ( size_t n = 0; n < N; n++ ) // index ordinal, not pointer + mUTF8WideStr[n] = wchar_t( BYTE(mUTF8Str[n]) ); // WARNING: First convert to "unsigned char" + + mUTF8WideStr[N] = 0; // add a final NULL + } + + return mUTF8WideStr; +} + + +/// UTF8: UTF8-Unicode Round-trip Conversions + +wchar_t* cUTF8::allocate( const char* in ) THROW( std::bad_alloc ) +{ + ASSERT( in /* && TSS_IsValidString( in )*/ ); // Verify Input + + size_t N = ::MultiByteToWideChar( CP_UTF8, 0, in, -1, 0, 0 ); + wchar_t* out = new wchar_t[ N + 1 ]; // Allocate required size + + + //--Convert + + out[0] = 0x00; // NOTE: Just in case we fail + #ifdef _DEBUG + //size_t nWritten = + #endif + ::MultiByteToWideChar( CP_UTF8, 0, in, -1, out, N ); + out[N] = 0; + +#ifdef _INTEG2 // Verify Output + if ( nWritten == 0 ) + { + cDebug d( "cUTF8::allocate" ); + d.TraceError( "MultiByteToWideChar failed with %x\n", ::GetLastError() ); + } + + ASSERT( out && TSS_IsValidString( out, nWritten ) ); +#endif + + return out; +} + +char* cUTF8::allocate( const wchar_t* in ) THROW( std::bad_alloc ) +{ + ASSERT( in /*&& TSS_IsValidString( in ) */); // Verify Input + + // Allocate required size + size_t N = ::WideCharToMultiByte( CP_UTF8, 0, in, -1,0,0,0,0 ); + char* out = new char[ N + 1 ]; + + + //--Convert + + out[0] = 0x00; // NOTE: Just in case we fail + #ifdef _DEBUG + //size_t nWritten = + #endif + ::WideCharToMultiByte( CP_UTF8, 0, in, -1, out, N, 0, 0 ); + out[N] = 0; + +#ifdef _INTEG2 // Verify Output + if ( nWritten == 0 ) + { + cDebug d( "cUTF8::allocate" ); + d.TraceError( "WideCharToMultiByte failed with %x\n", ::GetLastError() ); + } + + ASSERT( out /*&& TSS_IsValidString( out, nWritten ) */); +#endif + + return out; +} + +#endif //_UNICODE + diff --git a/src/core/utf8.h b/src/core/utf8.h new file mode 100644 index 0000000..302d971 --- /dev/null +++ b/src/core/utf8.h @@ -0,0 +1,187 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// utf8.h +// + +// UTF8 is used to map UNICODE characters to NTBS targets +// that would normally not be able to dealt with. UTF8 +// ensures symetrical round-trip conversions. In other +// words an unmapable UNICODE character converted to UTF8 +// will always convert back to the same UNICODE value. +// +// For more information, go to: +// mk:@MSITStore:\\SQUID\MSDN%20January%201999\MSDN\kbwindev.chm::/Source/win32sdk/q175392.htm + +#ifndef __UTF8_H +#define __UTF8_H + +#include // operator<< + +//#ifndef __TSS_INTEG_STRINGS_H +//#include "integ/tss.integ.strings.h" // IsValidAddress and IsValidString +//#endif +#ifndef __DEBUG_H +#include "debug.h" +#endif + +//----------------------------------------------------------------------------- +// convenience macros +// +// use these when printing a string ( TCHAR* ) to stdout, stderr, of printf-style +// function to safely convert the string to something printable +//----------------------------------------------------------------------------- +#ifdef _UNICODE +# define TSS_UTF8( x ) cUTF8( x ).wstr() +#else +# define TSS_UTF8( x ) x +#endif + +#ifdef _UNICODE // this class is only needed in unicode builds... + +//----------------------------------------------------------------------------- +// Entities Declared in this Module +//----------------------------------------------------------------------------- + +class cUTF8; + +std::ostream& operator<<( std::ostream&, const cUTF8& ); +std::wostream& operator<<( std::wostream&, const cUTF8& ); + + +/// Class Declaration + +#ifdef _THROW_SUPPORTED +#define THROW( x ) throw( x ) +#define THROW_0 throw() +#else +#define THROW( x ) +#define THROW_0 +#endif + +//============================================================================= +// class cUTF8: Encapsulate UTF8 Encoding +// +// SYNOPSIS: +// Allows unmappable UNICODE characters to be embedded into Narrow strings +// and displayable by narrow display streams. +// +// CONSTRAINTS: +// Cannot default or copy construct or assign UTF8 instances. Each UTF8 +// instance is an exclusive owner of its resources for its life-time. +// This cuts down on the amount of redundant allocation and copying that +// is required by the class. +//============================================================================= + +class cUTF8 +{ + /// Interface. + + public: + + cUTF8( const char* ) THROW( std::bad_alloc ); + cUTF8( const wchar_t* ) THROW( std::bad_alloc ); + ~cUTF8(); + + const char* str() const THROW( std::bad_alloc ); // Narrow UTF8 + const wchar_t* wstr() const THROW( std::bad_alloc ); // Wide UTF8 + const wchar_t* ustr() const THROW( std::bad_alloc ); // Unicode + + + /// Implementation. + + protected: + + static char* allocate( const wchar_t* ) THROW( std::bad_alloc ); + static wchar_t* allocate( const char* ) THROW( std::bad_alloc ); + + protected: + + cUTF8( const cUTF8& ); // Disallow + cUTF8& operator=( const cUTF8& ); // Disallow + + private: + + mutable wchar_t* mUnicodeStr; // UNICODE String + mutable char* mUTF8Str; // UTF8 Bytes String + mutable wchar_t* mUTF8WideStr; // UTF8 Wide Character String +}; + +//----------------------------------------------------------------------------- +// UTF8 Inlines: Members and Global Binary Non-Member Operators +//----------------------------------------------------------------------------- + +// Create from NTBS UTF8 +inline cUTF8::cUTF8( const char* psz ) THROW( std::bad_alloc ) +: mUnicodeStr( cUTF8::allocate( psz ) ), + mUTF8Str( 0 ), + mUTF8WideStr( 0 ) +{ + ASSERT( mUnicodeStr || mUTF8Str ); +} + +// Create from NTWCS UNICODE +inline cUTF8::cUTF8( const wchar_t* wsz ) THROW( std::bad_alloc ) +: mUnicodeStr( 0 ), + mUTF8Str( cUTF8::allocate( wsz ) ), + mUTF8WideStr( 0 ) +{ + ASSERT( mUnicodeStr || mUTF8Str ); +} + +inline cUTF8::~cUTF8() +{ + delete [] mUnicodeStr; // Delete UNICODE (if exists) + delete [] mUTF8Str; // Delete UTF8 (NTBS) + delete [] mUTF8WideStr; // Delete UTF8 (NTWCS) +} + + +/// Operators + +inline std::ostream& operator<<( std::ostream& out, const cUTF8& str ) +{ + out << str.str(); + return out; +} + +inline std::wostream& operator<<( std::wostream& wout, const cUTF8& str ) +{ + wout << str.wstr(); // CAUTION: Don't send UNICODE string, it won't display! + return wout; +} + + +#endif //_UNICODE + +#endif/*_TSS_UTF8_H*/ + diff --git a/src/core/wchar16.cpp b/src/core/wchar16.cpp new file mode 100644 index 0000000..a8b9ccc --- /dev/null +++ b/src/core/wchar16.cpp @@ -0,0 +1,339 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// wchar16.h +// +// Function and classes dealing with the WCHAR16 type +// +#include "stdcore.h" +#include "wchar16.h" +#include "debug.h" +#include // for stl::out_of_range +#include + +int wchar16len(const WCHAR16* s) +{ + int i; + for (i = 0; *s != 0; ++s, ++i) + ; + + return i; +} + +//============================================================================= +// class wc16_string +// +// This clas implements enough of the std::basic_string interface so we +// can use it like an STL string. +// +// In an ideal world we this would be a std::basic_string instantiation, but +// UNIX doesn't seem to dealing 16 bit wide chars, it uses 32 bit chars. +//============================================================================= + +class wc16_string_impl +{ +public: + int length; + WCHAR16* pString; + int refCount; + + wc16_string_impl(); + wc16_string_impl(const wc16_string_impl& rhs); + + void AddRef(); + void Release(); + void Resize(int newlen); + void CopyString(const wc16_string_impl& rhs); + // note: does not alter this->referenceCount, and ASSERTs that refcount == 1 + + ~wc16_string_impl(); // call Release() to delete +private: + void operator = (const wc16_string_impl& rhs) { return; } // don't call +}; + +static WCHAR16 NULL_WCHAR16 = 0; + +wc16_string::wc16_string() +: mpData(0) +{ +} + +wc16_string::wc16_string(const wc16_string& rhs) +{ + mpData = rhs.mpData; + if (mpData) + mpData->AddRef(); +} + +wc16_string::wc16_string(const_iterator pStr) +{ + mpData = new wc16_string_impl; + + int len = wchar16len(pStr); + mpData->Resize(len); + memcpy(mpData->pString, pStr, len * sizeof(WCHAR16)); +} + +wc16_string::~wc16_string() +{ + if (mpData) + mpData->Release(); +} + +void wc16_string::operator = (const wc16_string& rhs) +{ + if (mpData) + mpData->Release(); + + mpData = rhs.mpData; + + if( mpData ) + mpData->AddRef(); +} + + +int wc16_string::compare(const wc16_string& rhs) const +{ + if( length() > rhs.length() ) + return 1; + else if ( length() < rhs.length() ) + return -1; + else + return memcmp( c_str(), rhs.c_str(), length()*sizeof( WCHAR16 ) ); +} + +wc16_string::size_type +wc16_string::length() const +{ + return mpData ? mpData->length : 0; +} + +wc16_string::size_type +wc16_string::size() const +{ + return mpData ? mpData->length : 0; +} + +wc16_string::const_iterator +wc16_string::c_str() const +{ + if (mpData == 0) + return &NULL_WCHAR16; + + mpData->pString[mpData->length] = 0; + + return mpData->pString; +} + +wc16_string::const_iterator +wc16_string::begin() const +{ + return (const_cast(this))->begin(); +} + +wc16_string::iterator +wc16_string::begin() +{ + return mpData ? mpData->pString : &NULL_WCHAR16; +} + +wc16_string::const_iterator +wc16_string::end() const +{ + return + const_cast< iterator >( + mpData + ? mpData->pString + mpData->length + : &NULL_WCHAR16 ); +} + +wc16_string::iterator +wc16_string::end() +{ + return + mpData + ? mpData->pString + mpData->length + : &NULL_WCHAR16; +} + +wc16_string::const_iterator wc16_string::data() const +{ + return begin(); +} + +const wc16_string::value_type& wc16_string::operator [] (int i) const +{ + ASSERT(i >= 0); + + if (mpData == 0 || i >= mpData->length || i < 0) + { + ASSERT(false); + throw std::out_of_range("wc16_string[]"); + } + + return mpData->pString[i]; +} + +wc16_string::value_type& wc16_string::operator [] (int i) +{ + ASSERT(i >= 0); + + if (mpData == 0 || i >= mpData->length || i < 0) + { + ASSERT(false); + throw std::out_of_range("wc16_string[]"); + } + + if (mpData->refCount > 1) + { + wc16_string_impl* newImpl = new wc16_string_impl(*mpData); + mpData->Release(); + mpData = newImpl; + } + + return mpData->pString[i]; +} + +void wc16_string::resize( size_type nCount ) +{ + if ( mpData == 0 ) + { + mpData = new wc16_string_impl; + } + else if ( mpData->refCount > 1 ) + { + wc16_string_impl* newImpl = new wc16_string_impl( *mpData ); + mpData->Release(); + mpData = newImpl; + } + + mpData->Resize( nCount ); +} + +// useful to convert to network byte order +void wc16_string::swapbytes() +{ + if (mpData) + { + if (mpData->refCount > 1) + { + wc16_string_impl* newImpl = new wc16_string_impl(*mpData); + mpData->Release(); + mpData = newImpl; + } + + int i; + for (i = 0; i < mpData->length; ++i) + { + mpData->pString[i] = SWAPBYTES16(mpData->pString[i]); + } + } +} + +wc16_string_impl::wc16_string_impl() +{ + length = 0; + pString = new WCHAR16[1]; + refCount = 1; +} + +wc16_string_impl::wc16_string_impl(const wc16_string_impl& rhs) +{ + int newlen = rhs.length; + pString = new WCHAR16[newlen + 1]; + length = newlen; + refCount = 1; + + memcpy(pString, rhs.pString, newlen * sizeof(WCHAR16)); +} + +wc16_string_impl::~wc16_string_impl() +{ + delete [] pString; +} + +void wc16_string_impl::AddRef() +{ + ++refCount; +} + +void wc16_string_impl::Release() +{ + ASSERT(refCount > 0); + + if (--refCount == 0) + { + delete this; + } +} + +void wc16_string_impl::Resize(int newlen) +{ + ASSERT(newlen >= 0); + if (newlen == length) + return; + + WCHAR16* newString = new WCHAR16[newlen + 1]; + + if (newlen < length) + { + memcpy(newString, pString, newlen * sizeof(WCHAR16)); + delete [] pString; + pString = newString; + length = newlen; + } + else + { + memcpy(newString, pString, length * sizeof(WCHAR16)); + memset(newString + length, 0, (newlen - length) * sizeof(WCHAR16)); + delete [] pString; + pString = newString; + length = newlen; + } +} + +void wc16_string_impl::CopyString(const wc16_string_impl& rhs) +{ + ASSERT(refCount == 1); + + int newlen = rhs.length; + + if (rhs.length != this->length) + { + delete [] pString; + pString = new WCHAR16[newlen + 1]; + this->length = newlen; + } + + memcpy(this->pString, rhs.pString, newlen * sizeof(WCHAR16)); +} + diff --git a/src/core/wchar16.h b/src/core/wchar16.h new file mode 100644 index 0000000..74abe7f --- /dev/null +++ b/src/core/wchar16.h @@ -0,0 +1,118 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// wchar16.h +// +// Function ans classes dealing with the WCHAR16 type +// + +#ifndef __WCHAR16_H +#define __WCHAR16_H + +// TODO: Perhaps WCHAR16 should come out of types.h??? +#ifndef __TYPES_H +#include "types.h" +#endif + +#if WCHAR_IS_16_BITS +typedef unsigned short WCHAR16; +#else +typedef uint16 WCHAR16; // unix has 4 byte wchar_t, but we want to standardize on 16 bit wide chars +#endif + +//============================================================================= +// class wc16_string +// +// This clas implements enough of the std::basic_string interface so we +// can use it like an STL string. +// +// In an ideal world we this would be a std::basic_string instantiation, but +// UNIX doesn't seem to dealing 16 bit wide chars, it uses 32 bit chars. +// +// a WCHAR16 is a 16-bit UCS2 (Unicode v1.1) character +// +//============================================================================= + +class wc16_string_impl; + +// TODO:BAM -- check into reducing wc16_string to: +// typedef std::basic_string wc16_string; + +class wc16_string +{ +public: + + typedef WCHAR16 value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef size_t size_type; + + + wc16_string(); + wc16_string( const wc16_string& rhs); + wc16_string( const_iterator pStr); + + ~wc16_string(); + + void operator=( const wc16_string& rhs ); + int compare( const wc16_string& rhs ) const; + + size_type length() const; + size_type size() const; + + const_iterator begin() const; + iterator begin(); + + const_iterator end() const; + iterator end(); + + const_iterator c_str() const; + const_iterator data() const; + + bool empty() const + { + return length() == 0; + } + + const value_type& operator[]( int i ) const; // throw std::out_of_range + value_type& operator[]( int i ); // throw std::out_of_range + + void resize( size_type ); + void swapbytes(); // useful to convert to network byte order + +private: + + wc16_string_impl* mpData; +}; + +#endif + diff --git a/src/core/wchar16_t.cpp b/src/core/wchar16_t.cpp new file mode 100644 index 0000000..dc46480 --- /dev/null +++ b/src/core/wchar16_t.cpp @@ -0,0 +1,126 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// wchar16_t.h +// +// Function and classes dealing with the WCHAR16 type +// + +#include "stdcore.h" +#include "wchar16.h" +#include "test/test.h" + +void TestWchar16() +{ + cDebug db("TestWchar16()"); + + db.TraceAlways("Entering...\n"); + + wc16_string a; + TEST(a.length() == 0); + + wc16_string b(a); + TEST(b.empty()); + +//#if !IS_UNIX // need to get the L"" stuff working + + static WCHAR16 STRING1[] = { 65, 66, 67, 68, 0 }; + static WCHAR16 STRING2[] = { 40, 66, 67, 68, 0 }; + static WCHAR16 STRING0[] = { 65, 66, 67, 68, 0, 0 }; + + a = STRING1; + TEST(a.length() == 4); + TEST(memcmp(a.data(), STRING1, 4 * sizeof(WCHAR16)) == 0); + TEST(b.length() == 0); + + b = a; + TEST(b.length() == 4); + TEST(memcmp(b.data(), STRING1, 4 * sizeof(WCHAR16)) == 0); + + a.resize(3); + TEST(a.length() == 3); + TEST(memcmp(a.data(), STRING1, 3 * sizeof(WCHAR16)) == 0); + TEST(b.length() == 4); + TEST(memcmp(b.data(), STRING1, 4 * sizeof(WCHAR16)) == 0); + + b.resize(5); + TEST(memcmp(b.data(), STRING0, 5 * sizeof(WCHAR16)) == 0); + + a = STRING1; + b = a; + a[0] = 40; + TEST(a.length() == 4); + TEST(memcmp(a.data(), STRING2, 4 * sizeof(WCHAR16)) == 0); + TEST(b.length() == 4); + TEST(memcmp(b.data(), STRING1, 4 * sizeof(WCHAR16)) == 0); + + a = STRING1; + b = a; + a[0] = 40; + TEST(a.length() == 4); + TEST(memcmp(a.data(), STRING2, 4 * sizeof(WCHAR16)) == 0); + TEST(b.length() == 4); + TEST(memcmp(b.data(), STRING1, 4 * sizeof(WCHAR16)) == 0); + + a = b; + TEST(a[0] == b[0]); + TEST(a[1] == b[1]); + TEST(a[2] == b[2]); + TEST(a[3] == b[3]); + + const wc16_string c = a; + const wc16_string d = b; + TEST(c[0] == d[0]); + TEST(c[1] == d[1]); + TEST(c[2] == d[2]); + TEST(c[3] == d[3]); + +#if 0 // this is anoying due to ASSERT() in wchar16.cpp + try + { + TEST(a[4] > 0); + TEST(false); // exception did not get thrown + } + catch (std::out_of_range) + { + ; + } +#endif + + b.swapbytes(); + TEST(memcmp(a.data(), STRING1, 4) == 0); + b.swapbytes(); + TEST(memcmp(b.data(), STRING1, 4) == 0); +//#endif // IS_UNIX + + db.TraceAlways("Done...\n"); +} diff --git a/src/cryptlib/Makefile.am b/src/cryptlib/Makefile.am new file mode 100644 index 0000000..cddd77c --- /dev/null +++ b/src/cryptlib/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. -I../.. + +DEFAULT_INCLUDES = $(D_INCLUDES) + +noinst_LIBRARIES = libcryptlib.a +libcryptlib_a_SOURCES = \ + algebra.cpp asn.cpp cryptlib.cpp des.cpp dessp.cpp elgamal.cpp \ + eprecomp.cpp filters.cpp forkjoin.cpp integer.cpp iterhash.cpp misc.cpp \ + nbtheory.cpp pch.cpp queue.cpp rng.cpp sha.cpp zbits.cpp zdeflate.cpp \ + zinflate.cpp ztrees.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +CLEANFILES = ../../lib/libcryptlib.a + +all: $(noinst_LIBRARIES) + ln -f $(noinst_LIBRARIES) ../../lib/libcryptlib.a diff --git a/src/cryptlib/Makefile.in b/src/cryptlib/Makefile.in new file mode 100644 index 0000000..73cca5b --- /dev/null +++ b/src/cryptlib/Makefile.in @@ -0,0 +1,407 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libcryptlib_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/cryptlib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libcryptlib_a_AR = $(AR) $(ARFLAGS) +libcryptlib_a_LIBADD = +am_libcryptlib_a_OBJECTS = algebra.$(OBJEXT) asn.$(OBJEXT) \ + cryptlib.$(OBJEXT) des.$(OBJEXT) dessp.$(OBJEXT) \ + elgamal.$(OBJEXT) eprecomp.$(OBJEXT) filters.$(OBJEXT) \ + forkjoin.$(OBJEXT) integer.$(OBJEXT) iterhash.$(OBJEXT) \ + misc.$(OBJEXT) nbtheory.$(OBJEXT) pch.$(OBJEXT) \ + queue.$(OBJEXT) rng.$(OBJEXT) sha.$(OBJEXT) zbits.$(OBJEXT) \ + zdeflate.$(OBJEXT) zinflate.$(OBJEXT) ztrees.$(OBJEXT) +libcryptlib_a_OBJECTS = $(am_libcryptlib_a_OBJECTS) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libcryptlib_a_SOURCES) +DIST_SOURCES = $(libcryptlib_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. -I../.. +DEFAULT_INCLUDES = $(D_INCLUDES) +noinst_LIBRARIES = libcryptlib.a +libcryptlib_a_SOURCES = \ + algebra.cpp asn.cpp cryptlib.cpp des.cpp dessp.cpp elgamal.cpp \ + eprecomp.cpp filters.cpp forkjoin.cpp integer.cpp iterhash.cpp misc.cpp \ + nbtheory.cpp pch.cpp queue.cpp rng.cpp sha.cpp zbits.cpp zdeflate.cpp \ + zinflate.cpp ztrees.cpp + +CLEANFILES = ../../lib/libcryptlib.a +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/cryptlib/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/cryptlib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libcryptlib.a: $(libcryptlib_a_OBJECTS) $(libcryptlib_a_DEPENDENCIES) + -rm -f libcryptlib.a + $(libcryptlib_a_AR) libcryptlib.a $(libcryptlib_a_OBJECTS) $(libcryptlib_a_LIBADD) + $(RANLIB) libcryptlib.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + ln -f $(noinst_LIBRARIES) ../../lib/libcryptlib.a +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/cryptlib/algebra.cpp b/src/cryptlib/algebra.cpp new file mode 100644 index 0000000..6be0d6c --- /dev/null +++ b/src/cryptlib/algebra.cpp @@ -0,0 +1,6 @@ +// algebra.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "integer.h" +#include "algebra.h" + diff --git a/src/cryptlib/algebra.h b/src/cryptlib/algebra.h new file mode 100644 index 0000000..fdcd543 --- /dev/null +++ b/src/cryptlib/algebra.h @@ -0,0 +1,489 @@ +#ifndef ALGEBRA_H +#define ALGEBRA_H + +class Integer; + +template class AbstractGroup +{ +public: + typedef T Element; + + virtual ~AbstractGroup() {} + + virtual bool Equal(const Element &a, const Element &b) const =0; + virtual Element Zero() const =0; + virtual Element Add(const Element &a, const Element &b) const =0; + virtual Element Inverse(const Element &a) const =0; + + virtual Element Double(const Element &a) const; + virtual Element Subtract(const Element &a, const Element &b) const; + virtual Element& Accumulate(Element &a, const Element &b) const; + virtual Element& Reduce(Element &a, const Element &b) const; + + virtual Element IntMultiply(const Element &a, const Integer &e) const; + virtual Element CascadeIntMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; +}; + +template class AbstractRing : public AbstractGroup +{ +public: + typedef T Element; + + virtual bool IsUnit(const Element &a) const =0; + virtual Element One() const =0; + virtual Element Multiply(const Element &a, const Element &b) const =0; + virtual Element MultiplicativeInverse(const Element &a) const =0; + + virtual Element Square(const Element &a) const; + virtual Element Divide(const Element &a, const Element &b) const; + + virtual Element Exponentiate(const Element &a, const Integer &e) const; + virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; +}; + +// ******************************************************** + +// VC50 workaround: no member template support yet +template Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end); +#if defined(BREAK_GCC34) +template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end); +#endif /* BREAK_GCC34 */ + +// ******************************************************** + +template class AbstractField : public AbstractRing +{ +public: + bool IsUnit(const typename T::Element &a) const + {return !Equal(a, this->Zero());} +}; + +template class AbstractEuclideanDomain : public AbstractRing +{ +public: + typedef T Element; + + virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0; + + virtual Element Mod(const Element &a, const Element &b) const; + virtual Element Gcd(const Element &a, const Element &b) const; +}; + +// ******************************************************** + +template class MultiplicativeGroup : public AbstractGroup +{ +public: + typedef T Ring; + + MultiplicativeGroup(const Ring &m_ring) + : m_ring(m_ring) {} + + const Ring & GetRing() const + {return m_ring;} + + bool Equal(const typename T::Element &a, const typename T::Element &b) const + {return m_ring.Equal(a, b);} + + typename T::Element Zero() const + {return m_ring.One();} + + typename T::Element Add(const typename T::Element &a, const typename T::Element &b) const + {return m_ring.Multiply(a, b);} + + typename T::Element& Accumulate(typename T::Element &a, const typename T::Element &b) const + {return a = m_ring.Multiply(a, b);} + + typename T::Element Inverse(const typename T::Element &a) const + {return m_ring.MultiplicativeInverse(a);} + + typename T::Element Subtract(const typename T::Element &a, const typename T::Element &b) const + {return m_ring.Divide(a, b);} + + typename T::Element& Reduce(typename T::Element &a, const typename T::Element &b) const + {return a = m_ring.Divide(a, b);} + + typename T::Element Double(const typename T::Element &a) const + {return m_ring.Square(a);} + +protected: + const Ring &m_ring; +}; + +template class EuclideanDomainOf : public AbstractEuclideanDomain +{ +public: + typedef T Element; + + EuclideanDomainOf() {} + + bool Equal(const Element &a, const Element &b) const + {return a==b;} + + Element Zero() const + {return Element::Zero();} + + Element Add(const Element &a, const Element &b) const + {return a+b;} + + Element& Accumulate(Element &a, const Element &b) const + {return a+=b;} + + Element Inverse(const Element &a) const + {return -a;} + + Element Subtract(const Element &a, const Element &b) const + {return a-b;} + + Element& Reduce(Element &a, const Element &b) const + {return a-=b;} + + Element Double(const Element &a) const + {return a.Doubled();} + + Element One() const + {return Element::One();} + + Element Multiply(const Element &a, const Element &b) const + {return a*b;} + + Element Square(const Element &a) const + {return a.Squared();} + + bool IsUnit(const Element &a) const + {return a.IsUnit();} + + Element MultiplicativeInverse(const Element &a) const + {return a.MultiplicativeInverse();} + + Element Divide(const Element &a, const Element &b) const + {return a/b;} + + Element Mod(const Element &a, const Element &b) const + {return a%b;} + + void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const + {Element::Divide(r, q, a, d);} +}; + +template class QuotientRing : public AbstractRing +{ +public: + typedef T EuclideanDomain; + + QuotientRing(const EuclideanDomain &domain, const typename T::Element &modulus) + : m_domain(domain), m_modulus(modulus) {} + + const EuclideanDomain & GetDomain() const + {return m_domain;} + + const typename T::Element & GetModulus() const + {return m_modulus;} + + bool Equal(const typename T::Element &a, const typename T::Element &b) const + {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Zero());} + + typename T::Element Zero() const + {return m_domain.Zero();} + + typename T::Element Add(const typename T::Element &a, const typename T::Element &b) const + {return m_domain.Add(a, b);} + + typename T::Element& Accumulate(typename T::Element &a, const typename T::Element &b) const + {return m_domain.Accumulate(a, b);} + + typename T::Element Inverse(const typename T::Element &a) const + {return m_domain.Inverse(a);} + + typename T::Element Subtract(const typename T::Element &a, const typename T::Element &b) const + {return m_domain.Subtract(a, b);} + + typename T::Element& Reduce(typename T::Element &a, const typename T::Element &b) const + {return m_domain.Reduce(a, b);} + + typename T::Element Double(const typename T::Element &a) const + {return m_domain.Double(a);} + + bool IsUnit(const typename T::Element &a) const + {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));} + + typename T::Element One() const + {return m_domain.One();} + + typename T::Element Multiply(const typename T::Element &a, const typename T::Element &b) const + {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);} + + typename T::Element Square(const typename T::Element &a) const + {return m_domain.Mod(m_domain.Square(a), m_modulus);} + + typename QuotientRing::Element MultiplicativeInverse(const typename T::Element &a) const; + +protected: + const EuclideanDomain &m_domain; + typename T::Element m_modulus; +}; + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// BEGIN TEMPLATE DEFINITIONS + +#include +//USING_NAMESPACE(std) + +template T AbstractGroup::Double(const Element &a) const +{ + return Add(a, a); +} + +template T AbstractGroup::Subtract(const Element &a, const Element &b) const +{ + return Add(a, Inverse(b)); +} + +template T& AbstractGroup::Accumulate(Element &a, const Element &b) const +{ + return a = Add(a, b); +} + +template T& AbstractGroup::Reduce(Element &a, const Element &b) const +{ + return a = Subtract(a, b); +} + +template T AbstractRing::Square(const Element &a) const +{ + return Multiply(a, a); +} + +template T AbstractRing::Divide(const Element &a, const Element &b) const +{ + return Multiply(a, MultiplicativeInverse(b)); +} + +template T AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const +{ + Element r, q; + DivisionAlgorithm(r, q, a, b); + return r; +} + +template T AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const +{ + Element g[3]={b, a}; + unsigned int i0=0, i1=1, i2=2; + + while (!Equal(g[i1], this->Zero())) + { + g[i2] = Mod(g[i0], g[i1]); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return g[i0]; +} + +template typename QuotientRing::Element QuotientRing::MultiplicativeInverse(const typename T::Element &a) const +{ + typename T::Element g[3]={m_modulus, a}; + typename T::Element v[3]={m_domain.Zero(), m_domain.One()}; + typename T::Element y; + unsigned int i0=0, i1=1, i2=2; + + while (!Equal(g[i1], Zero())) + { + // y = g[i0] / g[i1]; + // g[i2] = g[i0] % g[i1]; + m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]); + // v[i2] = v[i0] - (v[i1] * y); + v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y)); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Zero(); +} + +template T AbstractGroup::IntMultiply(const Element &base, const Integer &exponent) const +{ + unsigned int expLen = exponent.BitCount(); + if (expLen==0) + return Zero(); + + unsigned powerTableSize = (expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 4 : (expLen <= 197 ? 8 : (expLen <= 539 ? 16 : (expLen <= 1434 ? 32 : 64)))))); + std::vector powerTable(powerTableSize); + + powerTable[0] = base; + if (powerTableSize > 1) + { + Element temp = Double(base); + for (unsigned i=1; i=0; i--) + { + power = 2*power + exponent.GetBit(i); + + if (i==0 || power >= powerTableSize) + { + unsigned squaresBefore = prevPosition-i; + unsigned squaresAfter = 0; + prevPosition = i; + while (power && power%2 == 0) + { + power /= 2; + squaresBefore--; + squaresAfter++; + } + if (firstTime) + { + result = powerTable[(power-1)/2]; + firstTime = false; + } + else + { + while (squaresBefore--) + result = Double(result); + if (power) + result = Add(powerTable[(power-1)/2], result); + } + while (squaresAfter--) + result = Double(result); + power = 0; + } + } + return result; +} + +template T AbstractGroup::CascadeIntMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount()); + if (expLen==0) + return Zero(); + + const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); + const unsigned tableSize = 1< powerTable(tableSize << w); + + powerTable[1] = x; + powerTable[tableSize] = y; + if (w==1) + powerTable[3] = Add(x,y); + else + { + powerTable[2] = Double(x); + powerTable[2*tableSize] = Double(y); + + unsigned i, j; + + for (i=3; i=0; i--) + { + power1 = 2*power1 + e1.GetBit(i); + power2 = 2*power2 + e2.GetBit(i); + + if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) + { + unsigned squaresBefore = prevPosition-i; + unsigned squaresAfter = 0; + prevPosition = i; + while ((power1 || power2) && power1%2 == 0 && power2%2==0) + { + power1 /= 2; + power2 /= 2; + squaresBefore--; + squaresAfter++; + } + if (firstTime) + { + result = powerTable[(power2< Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end) +{ + if (end-begin == 1) + return group.IntMultiply((*begin).second, (*begin).first); + else if (end-begin == 2) + return group.CascadeIntMultiply((*begin).second, (*begin).first, (*(begin+1)).second, (*(begin+1)).first); + else + { + Integer q, r; + Iterator last = end; + --last; + + make_heap(begin, end); + pop_heap(begin, end); + + while (!!(*begin).first) + { + // (*last).first is largest exponent, (*begin).first is next largest + Integer::Divide(r, q, (*last).first, (*begin).first); + + if (q == Integer::One()) + group.Accumulate((*begin).second, (*last).second); // avoid overhead of GeneralizedMultiplication() + else + group.Accumulate((*begin).second, group.IntMultiply((*last).second, q)); + + (*last).first = r; + + push_heap(begin, end); + pop_heap(begin, end); + } + + return group.IntMultiply((*last).second, (*last).first); + } +} + +template T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const +{ + return MultiplicativeGroup >(*this).IntMultiply(base, exponent); +} + +template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + return MultiplicativeGroup >(*this).CascadeIntMultiply(x, e1, y, e2); +} + +#if defined(BREAK_GCC34) +template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end) +{ + MultiplicativeGroup > mg(field); + return GeneralCascadeMultiplication(mg, begin, end); +} +#endif /* BREAK_GCC34 */ + +#endif diff --git a/src/cryptlib/asn.cpp b/src/cryptlib/asn.cpp new file mode 100644 index 0000000..883d47f --- /dev/null +++ b/src/cryptlib/asn.cpp @@ -0,0 +1,105 @@ +// asn.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "asn.h" +#include "misc.h" + +unsigned int DERLengthEncode(unsigned int length, byte *output) +{ + unsigned int i=0; + if (length <= 0x7f) + { + output[i++] = byte(length); + } + else + { + output[i++] = byte(BytePrecision(length) | 0x80); + for (int j=BytePrecision(length); j; --j) + { + output[i++] = byte (length >> (j-1)*8); + } + } + return i; +} + +unsigned int DERLengthEncode(unsigned int length, BufferedTransformation &bt) +{ + byte buf[10]; // should be more than enough + unsigned int i = DERLengthEncode(length, buf); + assert(i <= 10); + bt.Put(buf, i); + return i; +} + +bool BERLengthDecode(BufferedTransformation &bt, unsigned int &length) +{ + byte b; + + if (!bt.Get(b)) + BERDecodeError(); + + if (!(b & 0x80)) + length = b; + else + { + unsigned int lengthBytes = b & 0x7f; + if (bt.MaxRetrieveable() < lengthBytes) + BERDecodeError(); + + bt.Get(b); + while (!b && lengthBytes>1) + { + bt.Get(b); + lengthBytes--; + } + + switch (lengthBytes) + { + case 0: + return false; // indefinite length + case 1: + length = b; + break; + case 2: + length = b << 8; + length |= (bt.Get(b), b); + break; + default: + BERDecodeError(); + } + } + return true; +} + +BERSequenceDecoder::BERSequenceDecoder(BufferedTransformation &inQueue) + : inQueue(inQueue) +{ + byte b; + if (!inQueue.Get(b) || b != (SEQUENCE | CONSTRUCTED)) + BERDecodeError(); + + definiteLength = BERLengthDecode(inQueue, length); +} + +BERSequenceDecoder::~BERSequenceDecoder() +{ + if (!definiteLength) + { // remove end-of-content octects + word16 i; + if (!inQueue.GetShort(i) || (i!=0)) + BERDecodeError(); + } +} + +DERSequenceEncoder::DERSequenceEncoder(BufferedTransformation &outQueue) + : outQueue(outQueue) +{ +} + +DERSequenceEncoder::~DERSequenceEncoder() +{ + unsigned int length = (unsigned int)CurrentSize(); + outQueue.Put(SEQUENCE | CONSTRUCTED); + DERLengthEncode(length, outQueue); + TransferTo(outQueue); +} diff --git a/src/cryptlib/asn.h b/src/cryptlib/asn.h new file mode 100644 index 0000000..710f9e5 --- /dev/null +++ b/src/cryptlib/asn.h @@ -0,0 +1,58 @@ +#ifndef ASN_H +#define ASN_H + +#include "cryptlib.h" +#include "queue.h" + +// NOTE: these tags and flags are NOT COMPLETE! +enum ASNTag {INTEGER=0x02, BIT_STRING=0x03, SEQUENCE=0x10}; +enum ASNIdFlag {CONSTRUCTED = 0x20}; + +unsigned int DERLengthEncode(unsigned int length, byte *output); +unsigned int DERLengthEncode(unsigned int length, BufferedTransformation &); + +#ifdef THROW_EXCEPTIONS +#define BERDecodeError() throw BERDecodeErr() +#else +#define BERDecodeError() assert (false) +#endif + +class BERDecodeErr : public CryptlibException {public: BERDecodeErr() : CryptlibException("BER decode error") {}}; + +bool BERLengthDecode(BufferedTransformation &, unsigned int &); + +class BERSequenceDecoder : public BufferedTransformation +{ +public: + BERSequenceDecoder(BufferedTransformation &inQueue); + ~BERSequenceDecoder(); + + void Put(byte) {} + void Put(const byte *, unsigned int) {} + + unsigned long MaxRetrieveable() + {return inQueue.MaxRetrieveable();} + unsigned int Get(byte &outByte) + {return inQueue.Get(outByte);} + unsigned int Get(byte *outString, unsigned int getMax) + {return inQueue.Get(outString, getMax);} + unsigned int Peek(byte &outByte) const + {return inQueue.Peek(outByte);} + +private: + BufferedTransformation &inQueue; + bool definiteLength; + unsigned int length; +}; + +class DERSequenceEncoder : public ByteQueue +{ +public: + DERSequenceEncoder(BufferedTransformation &outQueue); + ~DERSequenceEncoder(); +private: + BufferedTransformation &outQueue; +}; + +#endif + diff --git a/src/cryptlib/config.h b/src/cryptlib/config.h new file mode 100644 index 0000000..53644dc --- /dev/null +++ b/src/cryptlib/config.h @@ -0,0 +1,210 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +// define this if you want the library to throw exceptions when things go wrong + +#define THROW_EXCEPTIONS + +// define this if your compiler doesn't support namespaces + +// NOTE:dmb For OST we will be using 2.95.2 which supports namespaces +//#ifdef __GNUC__ +//#define NO_NAMESPACE +//#endif + +// define this if your compiler only has the old version of iostream library + +// NOTE:dmb For OST we will be using the current ostreams +//#ifdef __GNUC__ +//#define OLD_IOSTREAM +//#endif + +// switch between different secure memory allocation mechnisms, this is the only +// one available right now + +#define SECALLOC_DEFAULT + +// Define this to 0 if your system doesn't differentiate between +// text mode and binary mode files. + +// #define BINARY_MODE 0 +#define BINARY_MODE ios::binary +// #define BINARY_MODE ios::bin + +// Define this to 0 if your compiler doesn't have ios::nocreate. +// This is needed because some compilers automaticly create a new file +// when you try to open one for reading if it doesn't already exist. + +#define FILE_NO_CREATE 0 +// #define FILE_NO_CREATE ios::nocreate + +// define this if you have a copy of RSAREF and want to compile the RSAREF +// class wrappers + +// #define USE_RSAREF + +// define this if you want to be able to initialize RSAREF structures with bignums + +// #define USE_BIGNUM_WITH_RSAREF + +#define GZIP_OS_CODE 0 + +// how much memory to use for deflation (compression) +// note 16 bit compilers don't work with BIG_MEM (pointer wraps around segment boundary) + +// #define SMALL_MEM +#define MEDIUM_MEM +// #define BIG_MEM + +// Define the following to use the updated standard SHA-1 instead of SHA + +#define NEW_SHA + +// Try this if your CPU has 256K internal cache or a slow multiply instruction +// and you want a (possibly) faster IDEA implementation using log tables + +// #define IDEA_LARGECACHE + +// Try this if you have a large cache or your CPU is slow manipulating +// individual bytes. + +// #define DIAMOND_USE_PERMTABLE + +// Define this if, for the linear congruential RNG, you want to use +// the original constants as specified in S.K. Park and K.W. Miller's +// CACM paper. + +// #define LCRNG_ORIGINAL_NUMBERS + +// Make sure these typedefs are correct for your computer + +typedef unsigned char byte; +typedef unsigned short word16; +#if SIZEOF_INT == 4 + typedef unsigned int word32; + #elif SIZEOF_LONG == 4 + typedef unsigned long word32; + #else + #error "I don't seem to have a 32-bit integer type on this system." +#endif + +// word should have the same size as your CPU registers +// dword should be twice as big as word + +#if defined(_MSC_VER) + +typedef unsigned __int32 word; +typedef unsigned __int64 dword; +#define WORD64_AVAILABLE +typedef unsigned __int64 word64; +#define W64LIT(x) x##i64 + +#elif defined(_KCC) + + #if defined(_ALPHA) + + typedef unsigned int word; + typedef unsigned long dword; + #define WORD64_AVAILABLE + typedef unsigned long word64; + #define W64LIT(x) x##LL + + #elif defined(_IRIX) + + typedef unsigned long word; + typedef unsigned long long dword; + #define WORD64_AVAILABLE + typedef unsigned long long word64; + #define W64LIT(x) x##LL + + #else + + typedef unsigned long word; + typedef unsigned long long dword; + #define WORD64_AVAILABLE + typedef unsigned long long word64; + #define W64LIT(x) x##LL + + #endif + +#elif defined(_SUNPRO) + +typedef unsigned long word; +typedef unsigned long long dword; +#define WORD64_AVAILABLE +typedef unsigned long long word64; +#define W64LIT(x) x##LL + +#elif defined(__GNUC__) + +typedef word32 word; +#if SIZEOF_LONG_LONG == 8 + typedef unsigned long long dword; + #define WORD64_AVAILABLE + typedef unsigned long long word64; + #define W64LIT(x) x##LL + #else + #error "I don't seem to have a 64-bit integer type on this system." +#endif +#else + +typedef unsigned int word; +typedef unsigned long dword; + +#endif + +// You may need to tweak this to fit your architecture +typedef unsigned long ptr_size_type; + +const unsigned int WORD_SIZE = sizeof(word); +const unsigned int WORD_BITS = WORD_SIZE * 8; + +#if defined(_IRIX) +#define LOW_WORD(x) (word)((x) & 0xffffffff) +#else +#define LOW_WORD(x) (word)(x) +#endif + +#ifdef WORDS_BIGENDIAN +#define HIGH_WORD(x) (*((word *)&(x))) +#else +#define HIGH_WORD(x) (*(((word *)&(x))+1)) +#endif + +// if the above HIGH_WORD macro doesn't work (if you are not sure, compile it +// and run the validation tests), try this: +// #define HIGH_WORD(x) (word)((x)>>WORD_BITS) + +#ifdef _MSC_VER +// 4250: dominance +// 4660: explicitly instantiating a class that's already implicitly instantiated +#pragma warning(disable: 4250 4660) +#endif + +#ifdef NO_NAMESPACE +#define std +#define USING_NAMESPACE(x) +#define NAMESPACE_BEGIN(x) +#define NAMESPACE_END +#define ANONYMOUS_NAMESPACE_BEGIN +#else +#define USING_NAMESPACE(x) using namespace x; +#define NAMESPACE_BEGIN(x) namespace x { +#define ANONYMOUS_NAMESPACE_BEGIN namespace { +#define NAMESPACE_END } +#endif + +#ifdef _MSC_VER +// VC50 workaround +#define STDMIN std::_cpp_min +#define STDMAX std::_cpp_max +#else +#define STDMIN std::min +#define STDMAX std::max +#endif + +#endif diff --git a/src/cryptlib/cryptest.dsp b/src/cryptlib/cryptest.dsp new file mode 100644 index 0000000..73e5eea --- /dev/null +++ b/src/cryptlib/cryptest.dsp @@ -0,0 +1,328 @@ +# Microsoft Developer Studio Project File - Name="cryptest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=cryptest - Win32 Unicode Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cryptest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cryptest.mak" CFG="cryptest - Win32 Unicode Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cryptest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 Unicode Release" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 Unicode Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName ""$/cryptlib/cryptest", FWAAAAAA" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cryptest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptes0" +# PROP BASE Intermediate_Dir "cryptes0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "CTRelease" +# PROP Intermediate_Dir "CTRelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib shell32.lib lib_r/cryptlib.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "cryptest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptes1" +# PROP BASE Intermediate_Dir "cryptes1" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "CTDebug" +# PROP Intermediate_Dir "CTDebug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib advapi32.lib lib_d/cryptlib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "cryptest - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptest___Win32_Unicode_Release" +# PROP BASE Intermediate_Dir "cryptest___Win32_Unicode_Release" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "cryptest_Unicode_Release" +# PROP Intermediate_Dir "cryptest_Unicode_Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /D "_UNICODE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib shell32.lib lib_r/cryptlib.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib shell32.lib cryptlib_Unicode_Release/cryptlib.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "cryptest - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptest___Win32_Unicode_Debug" +# PROP BASE Intermediate_Dir "cryptest___Win32_Unicode_Debug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "cryptest_Unicode_Debug" +# PROP Intermediate_Dir "cryptest_Unicode_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LITTLE_ENDIAN" /D "_UNICODE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib lib_d/cryptlib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib advapi32.lib cryptlib_Unicode_Debug/cryptlib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "cryptest - Win32 Release" +# Name "cryptest - Win32 Debug" +# Name "cryptest - Win32 Unicode Release" +# Name "cryptest - Win32 Unicode Debug" +# Begin Group "Data Files" + +# PROP Default_Filter ".dat;.txt" +# Begin Source File + +SOURCE=.\3wayval.dat +# End Source File +# Begin Source File + +SOURCE=.\blum1024.dat +# End Source File +# Begin Source File + +SOURCE=.\blum2048.dat +# End Source File +# Begin Source File + +SOURCE=.\blum512.dat +# End Source File +# Begin Source File + +SOURCE=.\castval.dat +# End Source File +# Begin Source File + +SOURCE=.\descert.dat +# End Source File +# Begin Source File + +SOURCE=.\dhparams.dat +# End Source File +# Begin Source File + +SOURCE=.\diamond.dat +# End Source File +# Begin Source File + +SOURCE=.\dsa1024.dat +# End Source File +# Begin Source File + +SOURCE=.\dsa512.dat +# End Source File +# Begin Source File + +SOURCE=.\elgc1024.dat +# End Source File +# Begin Source File + +SOURCE=.\elgc2048.dat +# End Source File +# Begin Source File + +SOURCE=.\elgc512.dat +# End Source File +# Begin Source File + +SOURCE=.\elgs1024.dat +# End Source File +# Begin Source File + +SOURCE=.\elgs2048.dat +# End Source File +# Begin Source File + +SOURCE=.\elgs512.dat +# End Source File +# Begin Source File + +SOURCE=.\gostval.dat +# End Source File +# Begin Source File + +SOURCE=.\havalcer.dat +# End Source File +# Begin Source File + +SOURCE=.\ideaval.dat +# End Source File +# Begin Source File + +SOURCE=.\luc1024.dat +# End Source File +# Begin Source File + +SOURCE=.\luc2048.dat +# End Source File +# Begin Source File + +SOURCE=.\luc512.dat +# End Source File +# Begin Source File + +SOURCE=.\lucc1024.dat +# End Source File +# Begin Source File + +SOURCE=.\lucc512.dat +# End Source File +# Begin Source File + +SOURCE=.\lucdif.dat +# End Source File +# Begin Source File + +SOURCE=.\lucs1024.dat +# End Source File +# Begin Source File + +SOURCE=.\lucs512.dat +# End Source File +# Begin Source File + +SOURCE=.\rabi1024.dat +# End Source File +# Begin Source File + +SOURCE=.\rabi2048.dat +# End Source File +# Begin Source File + +SOURCE=.\rabi512.dat +# End Source File +# Begin Source File + +SOURCE=.\rc5val.dat +# End Source File +# Begin Source File + +SOURCE=.\rsa1024.dat +# End Source File +# Begin Source File + +SOURCE=.\rsa2048.dat +# End Source File +# Begin Source File + +SOURCE=.\rsa512.dat +# End Source File +# Begin Source File + +SOURCE=.\rsa512a.dat +# End Source File +# Begin Source File + +SOURCE=.\saferval.dat +# End Source File +# Begin Source File + +SOURCE=.\sharkval.dat +# End Source File +# Begin Source File + +SOURCE=.\squareva.dat +# End Source File +# Begin Source File + +SOURCE=.\usage.dat +# End Source File +# End Group +# Begin Source File + +SOURCE=.\bench.cpp +# End Source File +# Begin Source File + +SOURCE=.\bench.h +# End Source File +# Begin Source File + +SOURCE=.\test.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat1.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat2.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat3.cpp +# End Source File +# Begin Source File + +SOURCE=.\validate.h +# End Source File +# End Target +# End Project diff --git a/src/cryptlib/cryptest.dsw b/src/cryptlib/cryptest.dsw new file mode 100644 index 0000000..7a55b03 --- /dev/null +++ b/src/cryptlib/cryptest.dsw @@ -0,0 +1,52 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cryptest"=".\cryptest.dsp" - Package Owner=<4> + +Package=<5> +{{{ + begin source code control + "$/Code/crypto++", JAHAAAAA + . + end source code control +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cryptlib + End Project Dependency +}}} + +############################################################################### + +Project: "cryptlib"=".\cryptlib.dsp" - Package Owner=<4> + +Package=<5> +{{{ + begin source code control + "$/Code/crypto++", JAHAAAAA + . + end source code control +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/cryptlib/cryptlib.cpp b/src/cryptlib/cryptlib.cpp new file mode 100644 index 0000000..df90bcf --- /dev/null +++ b/src/cryptlib/cryptlib.cpp @@ -0,0 +1,179 @@ +// cryptlib.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "cryptlib.h" +#include "misc.h" + +unsigned int RandomNumberGenerator::GetBit() +{ + return Parity(GetByte()); +} + +void RandomNumberGenerator::GetBlock(byte *output, unsigned int size) +{ + while (size--) + *output++ = GetByte(); +} + +word32 RandomNumberGenerator::GetLong(word32 min, word32 max) +{ + word32 range = max-min; + const int maxBytes = BytePrecision(range); + const int maxBits = BitPrecision(range); + + word32 value; + + do + { + value = 0; + for (int i=0; i range); + + return value+min; +} + +void StreamCipher::ProcessString(byte *outString, const byte *inString, unsigned int length) +{ + while(length--) + *outString++ = ProcessByte(*inString++); +} + +void StreamCipher::ProcessString(byte *inoutString, unsigned int length) +{ + while(length--) + *inoutString++ = ProcessByte(*inoutString); +} + +bool MessageAuthenticationCode::Verify(const byte *macIn) +{ + SecByteBlock mac(DigestSize()); + Final(mac); + return memcmp(mac, macIn, DigestSize()) == 0; +} + +void BufferedTransformation::TransferTo(BufferedTransformation &target) +{ + SecByteBlock buf(256); + unsigned int l; + + while ((l=Get(buf, 256)) != 0) + target.Put(buf, l); +} + +unsigned int BufferedTransformation::TransferTo(BufferedTransformation &target, unsigned int size) +{ + SecByteBlock buf(256); + unsigned int l, total = 0; + + while (size && (l=Get(buf, STDMIN(size, 256U)))) + { + target.Put(buf, l); + size -= l; + total += l; + } + return total; +} + +void BufferedTransformation::PutShort(word16 value, bool highFirst) +{ + if (highFirst) + { + Put(value>>8); + Put(byte(value)); + } + else + { + Put(byte(value)); + Put(value>>8); + } +} + +void BufferedTransformation::PutLong(word32 value, bool highFirst) +{ + if (highFirst) + { + for (int i=0; i<4; i++) + Put(byte(value>>((3-i)*8))); + } + else + { + for (int i=0; i<4; i++) + Put(byte(value>>(i*8))); + } +} + +int BufferedTransformation::GetShort(word16 &value, bool highFirst) +{ + if (MaxRetrieveable()<2) + return 0; + + byte buf[2]; + Get(buf, 2); + + if (highFirst) + value = (buf[0] << 8) | buf[1]; + else + value = (buf[1] << 8) | buf[0]; + + return 2; +} + +int BufferedTransformation::GetLong(word32 &value, bool highFirst) +{ + if (MaxRetrieveable()<4) + return 0; + + byte buf[4]; + Get(buf, 4); + + if (highFirst) + value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3]; + else + value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0]; + + return 4; +} + +unsigned int BufferedTransformation::Skip(unsigned int skipMax) +{ + byte b; + unsigned int skipActual=0; + + while (skipMax-- && Get(b)) + skipActual++; + return skipActual; +} + +unsigned int PK_FixedLengthCryptoSystem::MaxPlainTextLength(unsigned int cipherTextLength) const +{ + if (cipherTextLength == CipherTextLength()) + return MaxPlainTextLength(); + else + return 0; +} + +unsigned int PK_FixedLengthCryptoSystem::CipherTextLength(unsigned int plainTextLength) const +{ + if (plainTextLength <= MaxPlainTextLength()) + return CipherTextLength(); + else + return 0; +} + +unsigned int PK_FixedLengthDecryptor::Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) +{ + if (cipherTextLength != CipherTextLength()) + return 0; + + return Decrypt(cipherText, plainText); +} + +bool PK_VerifierWithRecovery::Verify(const byte *message, unsigned int messageLength, const byte *signature) +{ + SecByteBlock recovered(MaxMessageLength()); + unsigned int rLen = Recover(signature, recovered); + return (rLen==messageLength && memcmp(recovered, message, rLen)==0); +} diff --git a/src/cryptlib/cryptlib.dsp b/src/cryptlib/cryptlib.dsp new file mode 100644 index 0000000..60efd6c --- /dev/null +++ b/src/cryptlib/cryptlib.dsp @@ -0,0 +1,776 @@ +# Microsoft Developer Studio Project File - Name="cryptlib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=cryptlib - Win32 Unicode Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cryptlib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cryptlib.mak" CFG="cryptlib - Win32 Unicode Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cryptlib - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Unicode Release MinDependency" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Unicode Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Unicode Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName ""$/Code/Tripwire/2.0/ZZZ Consolidation Test/crypto", BAAAAAAA" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cryptlib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptlib" +# PROP BASE Intermediate_Dir "cryptlib" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "lib_r" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /Yu"pch.h" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptli0" +# PROP BASE Intermediate_Dir "cryptli0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "lib_d" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /Yu"pch.h" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Unicode Release MinDependency" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptlib" +# PROP BASE Intermediate_Dir "cryptlib" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../lib_r" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /Yu"pch.h" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptlib___Win32_Unicode_Release" +# PROP BASE Intermediate_Dir "cryptlib___Win32_Unicode_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "cryptlib_Unicode_Release" +# PROP Intermediate_Dir "cryptlib_Unicode_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /Yu"pch.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /D "_UNICODE" /Yu"pch.h" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptlib___Win32_Unicode_Debug" +# PROP BASE Intermediate_Dir "cryptlib___Win32_Unicode_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "cryptlib_Unicode_Debug" +# PROP Intermediate_Dir "cryptlib_Unicode_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /Yu"pch.h" /FD /c +# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "_LITTLE_ENDIAN" /D "_UNICODE" /Yu"pch.h" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "cryptlib - Win32 Release" +# Name "cryptlib - Win32 Debug" +# Name "cryptlib - Win32 Unicode Release MinDependency" +# Name "cryptlib - Win32 Unicode Release" +# Name "cryptlib - Win32 Unicode Debug" +# Begin Source File + +SOURCE=.\3way.cpp +# End Source File +# Begin Source File + +SOURCE=.\3way.h +# End Source File +# Begin Source File + +SOURCE=.\algebra.cpp +# End Source File +# Begin Source File + +SOURCE=.\algebra.h +# End Source File +# Begin Source File + +SOURCE=.\asn.cpp +# End Source File +# Begin Source File + +SOURCE=.\asn.h +# End Source File +# Begin Source File + +SOURCE=.\base64.cpp +# End Source File +# Begin Source File + +SOURCE=.\base64.h +# End Source File +# Begin Source File + +SOURCE=.\bfinit.cpp +# End Source File +# Begin Source File + +SOURCE=.\blowfish.cpp +# End Source File +# Begin Source File + +SOURCE=.\blowfish.h +# End Source File +# Begin Source File + +SOURCE=.\blumgold.cpp +# End Source File +# Begin Source File + +SOURCE=.\blumgold.h +# End Source File +# Begin Source File + +SOURCE=.\blumshub.cpp +# End Source File +# Begin Source File + +SOURCE=.\blumshub.h +# End Source File +# Begin Source File + +SOURCE=.\cast.cpp +# End Source File +# Begin Source File + +SOURCE=.\cast.h +# End Source File +# Begin Source File + +SOURCE=.\cast128s.cpp +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\crc.cpp +# End Source File +# Begin Source File + +SOURCE=.\crc.h +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.h +# End Source File +# Begin Source File + +SOURCE=.\default.cpp +# End Source File +# Begin Source File + +SOURCE=.\default.h +# End Source File +# Begin Source File + +SOURCE=.\des.cpp +# End Source File +# Begin Source File + +SOURCE=.\des.h +# End Source File +# Begin Source File + +SOURCE=.\dessp.cpp +# End Source File +# Begin Source File + +SOURCE=.\dh.cpp +# End Source File +# Begin Source File + +SOURCE=.\dh.h +# End Source File +# Begin Source File + +SOURCE=.\diamond.cpp +# End Source File +# Begin Source File + +SOURCE=.\diamond.h +# End Source File +# Begin Source File + +SOURCE=.\diamondt.cpp +# End Source File +# Begin Source File + +SOURCE=.\dsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\dsa.h +# End Source File +# Begin Source File + +SOURCE=.\ec2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\ec2n.h +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.cpp +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.h +# End Source File +# Begin Source File + +SOURCE=.\ecp.cpp +# End Source File +# Begin Source File + +SOURCE=.\ecp.h +# End Source File +# Begin Source File + +SOURCE=.\elgamal.cpp +# End Source File +# Begin Source File + +SOURCE=.\elgamal.h +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.cpp +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.h +# End Source File +# Begin Source File + +SOURCE=.\files.cpp +# End Source File +# Begin Source File + +SOURCE=.\files.h +# End Source File +# Begin Source File + +SOURCE=.\filters.cpp +# End Source File +# Begin Source File + +SOURCE=.\filters.h +# End Source File +# Begin Source File + +SOURCE=.\forkjoin.cpp +# End Source File +# Begin Source File + +SOURCE=.\forkjoin.h +# End Source File +# Begin Source File + +SOURCE=.\fstream +# End Source File +# Begin Source File + +SOURCE=.\gf256.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf256.h +# End Source File +# Begin Source File + +SOURCE=.\gf2_32.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf2_32.h +# End Source File +# Begin Source File + +SOURCE=.\gf2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf2n.h +# End Source File +# Begin Source File + +SOURCE=.\gost.cpp +# End Source File +# Begin Source File + +SOURCE=.\gost.h +# End Source File +# Begin Source File + +SOURCE=.\gzip.cpp +# End Source File +# Begin Source File + +SOURCE=.\gzip.h +# End Source File +# Begin Source File + +SOURCE=.\haval.cpp +# End Source File +# Begin Source File + +SOURCE=.\haval.h +# End Source File +# Begin Source File + +SOURCE=.\hex.cpp +# End Source File +# Begin Source File + +SOURCE=.\hex.h +# End Source File +# Begin Source File + +SOURCE=.\hmac.h +# End Source File +# Begin Source File + +SOURCE=.\idea.cpp +# End Source File +# Begin Source File + +SOURCE=.\idea.h +# End Source File +# Begin Source File + +SOURCE=.\integer.cpp +# End Source File +# Begin Source File + +SOURCE=.\integer.h +# End Source File +# Begin Source File + +SOURCE=.\iomanip +# End Source File +# Begin Source File + +SOURCE=.\iosfwd +# End Source File +# Begin Source File + +SOURCE=.\iostream +# End Source File +# Begin Source File + +SOURCE=.\iterhash.cpp +# End Source File +# Begin Source File + +SOURCE=.\iterhash.h +# End Source File +# Begin Source File + +SOURCE=.\lubyrack.h +# End Source File +# Begin Source File + +SOURCE=.\luc.cpp +# End Source File +# Begin Source File + +SOURCE=.\luc.h +# End Source File +# Begin Source File + +SOURCE=.\md5.cpp +# End Source File +# Begin Source File + +SOURCE=.\md5.h +# End Source File +# Begin Source File + +SOURCE=.\md5mac.cpp +# End Source File +# Begin Source File + +SOURCE=.\md5mac.h +# End Source File +# Begin Source File + +SOURCE=.\mdc.h +# End Source File +# Begin Source File + +SOURCE=.\misc.cpp +# End Source File +# Begin Source File + +SOURCE=.\misc.h +# End Source File +# Begin Source File + +SOURCE=.\modarith.h +# End Source File +# Begin Source File + +SOURCE=.\modes.cpp +# End Source File +# Begin Source File + +SOURCE=.\modes.h +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.cpp +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.h +# End Source File +# Begin Source File + +SOURCE=.\oaep.cpp +# End Source File +# Begin Source File + +SOURCE=.\oaep.h +# End Source File +# Begin Source File + +SOURCE=.\pch.cpp +# ADD CPP /Yc"pch.h" +# End Source File +# Begin Source File + +SOURCE=.\pch.h +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.cpp +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.h +# End Source File +# Begin Source File + +SOURCE=.\polynomi.cpp +# End Source File +# Begin Source File + +SOURCE=.\polynomi.h +# End Source File +# Begin Source File + +SOURCE=.\pubkey.cpp +# End Source File +# Begin Source File + +SOURCE=.\pubkey.h +# End Source File +# Begin Source File + +SOURCE=.\queue.cpp +# End Source File +# Begin Source File + +SOURCE=.\queue.h +# End Source File +# Begin Source File + +SOURCE=.\rabin.cpp +# End Source File +# Begin Source File + +SOURCE=.\rabin.h +# End Source File +# Begin Source File + +SOURCE=.\randpool.cpp +# End Source File +# Begin Source File + +SOURCE=.\randpool.h +# End Source File +# Begin Source File + +SOURCE=.\rc5.cpp +# End Source File +# Begin Source File + +SOURCE=.\rc5.h +# End Source File +# Begin Source File + +SOURCE=.\ripemd.cpp +# End Source File +# Begin Source File + +SOURCE=.\ripemd.h +# End Source File +# Begin Source File + +SOURCE=.\rng.cpp +# End Source File +# Begin Source File + +SOURCE=.\rng.h +# End Source File +# Begin Source File + +SOURCE=.\rsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\rsa.h +# End Source File +# Begin Source File + +SOURCE=.\rsarefcl.cpp +# End Source File +# Begin Source File + +SOURCE=.\rsarefcl.h +# End Source File +# Begin Source File + +SOURCE=.\safer.cpp +# End Source File +# Begin Source File + +SOURCE=.\safer.h +# End Source File +# Begin Source File + +SOURCE=.\sapphire.cpp +# End Source File +# Begin Source File + +SOURCE=.\sapphire.h +# End Source File +# Begin Source File + +SOURCE=.\seal.cpp +# End Source File +# Begin Source File + +SOURCE=.\seal.h +# End Source File +# Begin Source File + +SOURCE=.\secshare.cpp +# End Source File +# Begin Source File + +SOURCE=.\secshare.h +# End Source File +# Begin Source File + +SOURCE=.\secsplit.cpp +# End Source File +# Begin Source File + +SOURCE=.\secsplit.h +# End Source File +# Begin Source File + +SOURCE=.\sha.cpp +# End Source File +# Begin Source File + +SOURCE=.\sha.h +# End Source File +# Begin Source File + +SOURCE=.\shark.cpp +# End Source File +# Begin Source File + +SOURCE=.\shark.h +# End Source File +# Begin Source File + +SOURCE=.\sharkbox.cpp +# End Source File +# Begin Source File + +SOURCE=.\smartptr.h +# End Source File +# Begin Source File + +SOURCE=.\square.cpp +# End Source File +# Begin Source File + +SOURCE=.\square.h +# End Source File +# Begin Source File + +SOURCE=.\squaretb.cpp +# End Source File +# Begin Source File + +SOURCE=.\strstream +# End Source File +# Begin Source File + +SOURCE=.\tea.cpp +# End Source File +# Begin Source File + +SOURCE=.\tea.h +# End Source File +# Begin Source File + +SOURCE=.\tiger.cpp +# End Source File +# Begin Source File + +SOURCE=.\tiger.h +# End Source File +# Begin Source File + +SOURCE=.\tigertab.cpp +# End Source File +# Begin Source File + +SOURCE=.\wake.cpp +# End Source File +# Begin Source File + +SOURCE=.\wake.h +# End Source File +# Begin Source File + +SOURCE=.\words.h +# End Source File +# Begin Source File + +SOURCE=.\xormac.h +# End Source File +# Begin Source File + +SOURCE=.\zbits.cpp +# End Source File +# Begin Source File + +SOURCE=.\zbits.h +# End Source File +# Begin Source File + +SOURCE=.\zdeflate.cpp +# End Source File +# Begin Source File + +SOURCE=.\zdeflate.h +# End Source File +# Begin Source File + +SOURCE=.\zinflate.cpp +# End Source File +# Begin Source File + +SOURCE=.\zinflate.h +# End Source File +# Begin Source File + +SOURCE=.\ztrees.cpp +# End Source File +# Begin Source File + +SOURCE=.\ztrees.h +# End Source File +# End Target +# End Project diff --git a/src/cryptlib/cryptlib.h b/src/cryptlib/cryptlib.h new file mode 100644 index 0000000..1ad4e72 --- /dev/null +++ b/src/cryptlib/cryptlib.h @@ -0,0 +1,515 @@ +// cryptlib.h - written and placed in the public domain by Wei Dai + +// This file contains the declarations for the abstract base +// classes that provide a uniform interface to this library. + +#ifndef CRYPTLIB_H +#define CRYPTLIB_H + +#include "config.h" +#include +#include + +/// base class for all exceptions thrown by Crypto++ +class CryptlibException : public std::exception +{ +public: + explicit CryptlibException(const std::string& s) : m_what(s) {} + virtual ~CryptlibException() throw() {} + const char *what() const throw() {return (m_what.c_str());} + +private: + std::string m_what; +}; + +/// used to specify a direction for a cipher to operate in (encrypt or decrypt) +enum CipherDir { + /// + ENCRYPTION, + /// + DECRYPTION}; + + +/// abstract base class for block ciphers + +/** A particular derived class may change state as blocks are processed, + so the ProcessBlock() functions are not specified to be const. + + However, most classes derived from BlockTransformation are block ciphers + in ECB mode (for example the DESEncryption class), which are stateless. + These classes should not be used directly, but only in combination with + a mode class (see \Ref{Mode}). However, if you know what you are doing, and + need to call ProcessBlock() on a const ECB cipher object, you can safely + cast away its constness. + + Note: BlockTransformation objects may assume that pointers to input and + output blocks are aligned on 32-bit word boundaries. +*/ +class BlockTransformation +{ +public: + /// + virtual ~BlockTransformation() {} + + /// encrypt or decrypt one block in place + //* Precondition: size of inoutBlock == BlockSize(). + virtual void ProcessBlock(byte *inoutBlock) =0; + + /// encrypt or decrypt one block, may assume inBlock != outBlock + //* Precondition: size of inBlock and outBlock == BlockSize(). + virtual void ProcessBlock(const byte *inBlock, byte *outBlock) =0; + + /// block size of the cipher in bytes + virtual unsigned int BlockSize() const =0; +}; + + +/// abstract base class for stream ciphers + +class StreamCipher +{ +public: + /// + virtual ~StreamCipher() {} + + /// encrypt or decrypt one byte + virtual byte ProcessByte(byte input) =0; + + /// encrypt or decrypt an array of bytes of specified length in place + virtual void ProcessString(byte *inoutString, unsigned int length); + /// encrypt or decrypt an array of bytes of specified length, may assume inString != outString + virtual void ProcessString(byte *outString, const byte *inString, unsigned int length); +}; + +/// abstract base class for random access stream ciphers + +class RandomAccessStreamCipher : public virtual StreamCipher +{ +public: + /// + virtual ~RandomAccessStreamCipher() {} + /*/ specify that the next byte to be processed is at absolute position n + in the plaintext/ciphertext stream */ + virtual void Seek(unsigned long n) =0; +}; + +/// abstract base class for random number generators +/** All return values are uniformly distributed over the range specified. +*/ +class RandomNumberGenerator +{ +public: + /// + virtual ~RandomNumberGenerator() {} + + /// generate new random byte and return it + virtual byte GetByte() =0; + + /// generate new random bit and return it + /** Default implementation is to call GetByte() and return its parity. */ + virtual unsigned int GetBit(); + + /// generate a random 32 bit word in the range min to max, inclusive + virtual word32 GetLong(word32 a=0, word32 b=0xffffffffL); + /// generate a random 16 bit word in the range min to max, inclusive + virtual word16 GetShort(word16 a=0, word16 b=0xffff) + {return (word16)GetLong(a, b);} + + /// generate random array of bytes + //* Default implementation is to call GetByte size times. + virtual void GetBlock(byte *output, unsigned int size); +}; + +/// randomly shuffle the specified array, resulting permutation is uniformly distributed +template void Shuffle(RandomNumberGenerator &rng, T *array, unsigned int size) +{ + while (--size) + swap(array[size], array[(unsigned int)rng.GetLong(0, size)]); +} + +/// abstract base class for hash functions +/** HashModule objects are stateful. They are created in an initial state, + change state as Update() is called, and return to the initial + state when Final() is called. This interface allows a large message to + be hashed in pieces by calling Update() on each piece followed by + calling Final(). +*/ +class HashModule +{ +public: + /// + virtual ~HashModule() {} + + /// process more input + virtual void Update(const byte *input, unsigned int length) =0; + + /*/ calculate hash for the current message (the concatenation of all + inputs passed in via Update()), then reinitialize the object */ + //* Precondition: size of digest == DigestSize(). + virtual void Final(byte *digest) =0; + + /// size of the hash returned by Final() + virtual unsigned int DigestSize() const =0; + + /// use this if your input is short and you don't want to call Update() and Final() seperately + virtual void CalculateDigest(byte *digest, const byte *input, int length) + {Update(input, length); Final(digest);} +}; + +/// abstract base class for message authentication codes + +/** The main differences between a MAC and an hash function (in terms of + programmatic interface) is that a MAC is keyed, and that calculating + a MAC for the same message twice may produce two different results so + verifying a MAC may not be simply recalculating it and doing a bitwise + comparison. +*/ +class MessageAuthenticationCode : public virtual HashModule +{ +public: + /// + virtual ~MessageAuthenticationCode() {} + + /// verify that mac is a valid MAC for the current message, then reinitialize the object + /** Default implementation is to call Final() and do a bitwise comparison + between its output and mac. */ + virtual bool Verify(const byte *mac); + + /// use this if your input is short and you don't want to call Update() and Verify() seperately + virtual bool VerifyMAC(const byte *mac, const byte *input, int length) + {Update(input, length); return Verify(mac);} +}; + +/// abstract base class for buffered transformations + +/** BufferedTransformation is a generalization of \Ref{BlockTransformation}, + \Ref{StreamCipher}, and \Ref{HashModule}. + + A buffered transformation is an object that takes a stream of bytes + as input (this may be done in stages), does some computation on them, and + then places the result into an internal buffer for later retrieval. Any + partial result already in the output buffer is not modified by further + input. + + Computation is generally done as soon as possible, but some buffering + on the input may be done for performance reasons. +*/ +class BufferedTransformation +{ +public: + /// + virtual ~BufferedTransformation() {} + + //@Man: INPUT + //@{ + /// input a byte for processing + virtual void Put(byte inByte) =0; + /// input multiple bytes + virtual void Put(const byte *inString, unsigned int length) =0; + /// signal that no more input is available + virtual void InputFinished() {} + + /// input a 16-bit word, big-endian or little-endian depending on highFirst + void PutShort(word16 value, bool highFirst=true); + /// input a 32-bit word + void PutLong(word32 value, bool highFirst=true); + //@} + + //@Man: RETRIEVAL + //@{ + /// returns number of bytes that is currently ready for retrieval + /** All retrieval functions return the actual number of bytes + retrieved, which is the lesser of the request number and + MaxRetrieveable(). */ + virtual unsigned long MaxRetrieveable() =0; + + /// try to retrieve a single byte + virtual unsigned int Get(byte &outByte) =0; + /// try to retrieve multiple bytes + virtual unsigned int Get(byte *outString, unsigned int getMax) =0; + + /// try to retrieve a 16-bit word, big-endian or little-endian depending on highFirst + int GetShort(word16 &value, bool highFirst=true); + /// try to retrieve a 32-bit word + int GetLong(word32 &value, bool highFirst=true); + + /// move all of the buffered output to target as input + virtual void TransferTo(BufferedTransformation &target); + /// same as above but only transfer up to transferMax bytes + virtual unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax); + + /// peek at the next byte without removing it from the output buffer + virtual unsigned int Peek(byte &outByte) const =0; + + /// discard some bytes from the output buffer + unsigned int Skip(unsigned int skipMax); + //@} + + //@Man: ATTACHMENT + //@{ + /** Some BufferedTransformation objects (e.g. \Ref{Filter} objects) + allow other BufferedTransformation objects to be attached. When + this is done, the first object instead of buffering its output, + sents that output to the attached object as input. See the + documentation for the \Ref{Filter} class for the details. + */ + /// + virtual bool Attachable() {return false;} + /// + virtual void Detach(BufferedTransformation *p = 0) {} // NULL is undefined at this point + /// + virtual void Attach(BufferedTransformation *) {} + /// call InputFinished() for all attached objects + virtual void Close() {InputFinished();} + //@} +}; + +/// abstract base class for public-key encryptors and decryptors + +/** This class provides an interface common to encryptors and decryptors + for querying their plaintext and ciphertext lengths. +*/ +class PK_CryptoSystem +{ +public: + /// + virtual ~PK_CryptoSystem() {} + + /// maximum length of plaintext for a given ciphertext length + //* This function returns 0 if cipherTextLength is not valid (too long or too short). + virtual unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const =0; + + /// calculate length of ciphertext given length of plaintext + //* This function returns 0 if plainTextLength is not valid (too long). + virtual unsigned int CipherTextLength(unsigned int plainTextLength) const =0; +}; + +/// abstract base class for public-key encryptors + +/** An encryptor is also a public encryption key. It contains both the + key and the algorithm to perform the encryption. +*/ +class PK_Encryptor : public virtual PK_CryptoSystem +{ +public: + /// encrypt a byte string + /** Preconditions: + \begin{itemize} + \item CipherTextLength(plainTextLength) != 0 (i.e., plainText isn't too long) + \item size of cipherText == CipherTextLength(plainTextLength) + \end{itemize} + */ + virtual void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) =0; +}; + +/// abstract base class for public-key decryptors + +/** An decryptor is also a private decryption key. It contains both the + key and the algorithm to perform the decryption. +*/ +class PK_Decryptor : public virtual PK_CryptoSystem +{ +public: + /// decrypt a byte string, and return the length of plaintext + /** Precondition: size of plainText == MaxPlainTextLength(cipherTextLength) + bytes. + + The function returns the actual length of the plaintext, or 0 + if decryption fails. + */ + virtual unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) =0; +}; + +/// abstract base class for encryptors and decryptors with fixed length ciphertext + +/** A simplified interface (as embodied in this + class and its subclasses) is provided for crypto systems (such + as RSA) whose ciphertext depend only on the key, not on the length + of the plaintext. The maximum plaintext length also depend only on + the key. +*/ +class PK_FixedLengthCryptoSystem : public virtual PK_CryptoSystem +{ +public: + /// + virtual unsigned int MaxPlainTextLength() const =0; + /// + virtual unsigned int CipherTextLength() const =0; + + unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const; + unsigned int CipherTextLength(unsigned int plainTextLength) const; +}; + +/// abstract base class for encryptors with fixed length ciphertext + +class PK_FixedLengthEncryptor : public virtual PK_Encryptor, public virtual PK_FixedLengthCryptoSystem +{ +}; + +/// abstract base class for decryptors with fixed length ciphertext + +class PK_FixedLengthDecryptor : public virtual PK_Decryptor, public virtual PK_FixedLengthCryptoSystem +{ +public: + /// decrypt a byte string, and return the length of plaintext + /** Preconditions: + \begin{itemize} + \item length of cipherText == CipherTextLength() + \item size of plainText == MaxPlainTextLength() + \end{itemize} + + The function returns the actual length of the plaintext, or 0 + if decryption fails. + */ + virtual unsigned int Decrypt(const byte *cipherText, byte *plainText) =0; + + unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText); +}; + +/// abstract base class for public-key signers and verifiers + +/** This class provides an interface common to signers and verifiers + for querying their signature lengths and maximum message lengths. + + The maximum message length is typically very low (less than 1000) + because it is intended that only message digests (see \Ref{HashModule}) + should be signed. +*/ +class PK_SignatureSystem +{ +public: + /// + virtual ~PK_SignatureSystem() {}; + + /// maximum length of a message that can be signed or verified + virtual unsigned int MaxMessageLength() const =0; + /// signature length support by this object (as either input or output) + virtual unsigned int SignatureLength() const =0; +}; + +/// abstract base class for public-key signers + +/** A signer is also a private signature key. It contains both the + key and the algorithm to perform the signature. +*/ +class PK_Signer : public virtual PK_SignatureSystem +{ +public: + /// sign a message + /** Preconditions: + \begin{itemize} + \item messageLen <= MaxMessageLength() + \item size of signature == SignatureLength() + \end{itemize} + */ + virtual void Sign(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) =0; +}; + +/// abstract base class for public-key verifiers + +/** A verifier is also a public verification key. It contains both the + key and the algorithm to perform the verification. +*/ +class PK_Verifier : public virtual PK_SignatureSystem +{ +public: + /// check whether sig is a valid signature for message + /** Preconditions: + \begin{itemize} + \item messageLen <= MaxMessageLength() + \item length of signature == SignatureLength() + \end{itemize} + */ + virtual bool Verify(const byte *message, unsigned int messageLen, const byte *sig) =0; +}; + +/// abstract base class for public-key verifiers with recovery + +/** In a signature scheme with recovery, a verifier is able to extract + a message from its valid signature. This saves space since + you don't need to store the message seperately. +*/ +class PK_VerifierWithRecovery : public PK_Verifier +{ +public: + /// recover a message from its signature, return length of message, or 0 if signature is invalid + /** Preconditions: + \begin{itemize} + \item length of signature == SignatureLength() + \item size of recoveredMessage == MaxMessageLength() + \end{itemize} + */ + virtual unsigned int Recover(const byte *signature, byte *recoveredMessage) =0; + + bool Verify(const byte *message, unsigned int messageLen, const byte *signature); +}; + +/// abstract base class for key agreement protocols + +/** This class defines the interface for symmetric 2-pass key agreement + protocols. It isn't very general and only basic Diffie-Hellman + protocols fit the abstraction, so possibly a more general interface + is needed. + + To use a KeyAgreementProtocol class, the two parties create matching + KeyAgreementProtocol objects, call Setup() on these objects, + and send each other the public values produced. The objects are + responsible for remembering the corresponding secret values, and + will produce a shared secret value when Agree() is called with the + other party's public value. +*/ +class KeyAgreementProtocol +{ +public: + /// + virtual ~KeyAgreementProtocol() {} + + /// + virtual unsigned int PublicValueLength() const =0; + /// + virtual unsigned int AgreedKeyLength() const =0; + + /// produce public value + //* Precondition: size of publicValue == PublicValueLength() + virtual void Setup(RandomNumberGenerator &rng, byte *publicValue) =0; + + /// calculate agreed key given other party's public value + /** Precondition: + \begin{itemize} + \item Setup() was called previously on this object + \item size of agreedKey == AgreedKeyLength() + \end{itemize} + */ + virtual void Agree(const byte *otherPublicValue, byte *agreedKey) const =0; +}; + +/// abstract base class for all objects that support precomputation + +/** The class defines a common interface for doing precomputation, + and loading and saving precomputation. +*/ +class PK_Precomputation +{ +public: + /// + virtual ~PK_Precomputation() {} + + /// + /** The exact semantics of Precompute() is varies, but + typically it means calculate a table of n objects + that can be used later to speed up computation. + */ + virtual void Precompute(unsigned int n) =0; + + /// retrieve previously saved precomputation + virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) =0; + /// save precomputation for later use + virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const =0; +}; + +/// +template class PK_WithPrecomputation : public T, public virtual PK_Precomputation +{ +}; + +#endif diff --git a/src/cryptlib/des.cpp b/src/cryptlib/des.cpp new file mode 100644 index 0000000..a1f40e4 --- /dev/null +++ b/src/cryptlib/des.cpp @@ -0,0 +1,420 @@ +// des.cpp - modified by Wei Dai from: + +/* + * This is a major rewrite of my old public domain DES code written + * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 + * public domain code. I pretty much kept my key scheduling code, but + * the actual encrypt/decrypt routines are taken from from Richard + * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." + * + * This code is in the public domain. I would appreciate bug reports and + * enhancements. + * + * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. + */ + +#include "config.h" +#include "pch.h" +#include "misc.h" +#include "des.h" + +/* Tables defined in the Data Encryption Standard documents + * Three of these tables, the initial permutation, the final + * permutation and the expansion operator, are regular enough that + * for speed, we hard-code them. They're here for reference only. + * Also, the S and P boxes are used by a separate program, gensp.c, + * to build the combined SP box, Spbox[]. They're also here just + * for reference. + */ +#ifdef notdef +/* initial permutation IP */ +static byte ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static byte fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; +/* expansion operation matrix */ +static byte ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +/* The (in)famous S-boxes */ +static byte sbox[8][64] = { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + + /* S4 */ + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + + /* S5 */ + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + + /* S7 */ + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +static byte p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; +#endif + +/* permuted choice table (key) */ +static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + +/* Set key (initialize key schedule array) */ +DES::DES(const byte *key, CipherDir dir) + : k(32) +{ + SecByteBlock buffer(56+56+8); + byte *const pc1m=buffer; /* place to modify pc1 into */ + byte *const pcr=pc1m+56; /* place to rotate pc1 into */ + byte *const ks=pcr+56; + register unsigned int i,j,l; + int m; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,8); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + k[2*i] = ((word32)ks[0] << 24) + | ((word32)ks[2] << 16) + | ((word32)ks[4] << 8) + | ((word32)ks[6]); + k[2*i+1] = ((word32)ks[1] << 24) + | ((word32)ks[3] << 16) + | ((word32)ks[5] << 8) + | ((word32)ks[7]); + } + + if (dir==DECRYPTION) // reverse key schedule order + for (i=0; i<16; i+=2) + { + std::swap(k[i], k[32-2-i]); + std::swap(k[i+1], k[32-1-i]); + } +} +/* End of C code common to both versions */ + +/* C code only in portable version */ + +// Richard Outerbridge's initial permutation algorithm +/* +inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = rotl(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotl(left, 1); +} +inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotr(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotr(left, 1); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; +} +*/ + +// Wei Dai's modification to Richard Outerbridge's initial permutation +// algorithm, this one is faster if you have access to rotate instructions +// (like in MSVC) +inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotl(right, 4U); + work = (left ^ right) & 0xf0f0f0f0; + left ^= work; + right = rotr(right^work, 20U); + work = (left ^ right) & 0xffff0000; + left ^= work; + right = rotr(right^work, 18U); + work = (left ^ right) & 0x33333333; + left ^= work; + right = rotr(right^work, 6U); + work = (left ^ right) & 0x00ff00ff; + left ^= work; + right = rotl(right^work, 9U); + work = (left ^ right) & 0xaaaaaaaa; + left = rotl(left^work, 1U); + right ^= work; +} + +inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotr(right, 1U); + work = (left ^ right) & 0xaaaaaaaa; + right ^= work; + left = rotr(left^work, 9U); + work = (left ^ right) & 0x00ff00ff; + right ^= work; + left = rotl(left^work, 6U); + work = (left ^ right) & 0x33333333; + right ^= work; + left = rotl(left^work, 18U); + work = (left ^ right) & 0xffff0000; + right ^= work; + left = rotl(left^work, 20U); + work = (left ^ right) & 0xf0f0f0f0; + right ^= work; + left = rotr(left^work, 4U); +} + +// Encrypt or decrypt a block of data in ECB mode +void DES::ProcessBlock(const byte *inBlock, byte * outBlock) +{ + word32 l,r,work; + +#ifdef WORDS_BIGENDIAN + l = *(word32 *)inBlock; + r = *(word32 *)(inBlock+4); +#else + l = byteReverse(*(word32 *)inBlock); + r = byteReverse(*(word32 *)(inBlock+4)); +#endif + + IPERM(l,r); + + const word32 *kptr=k; + + for (unsigned i=0; i<8; i++) + { + work = rotr(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotr(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + FPERM(l,r); + +#ifdef WORDS_BIGENDIAN + *(word32 *)outBlock = r; + *(word32 *)(outBlock+4) = l; +#else + *(word32 *)outBlock = byteReverse(r); + *(word32 *)(outBlock+4) = byteReverse(l); +#endif +} + +void DES_EDE_Encryption::ProcessBlock(byte *inoutBlock) +{ + e.ProcessBlock(inoutBlock); + d.ProcessBlock(inoutBlock); + e.ProcessBlock(inoutBlock); +} + +void DES_EDE_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) +{ + e.ProcessBlock(inBlock, outBlock); + d.ProcessBlock(outBlock); + e.ProcessBlock(outBlock); +} + +void DES_EDE_Decryption::ProcessBlock(byte *inoutBlock) +{ + d.ProcessBlock(inoutBlock); + e.ProcessBlock(inoutBlock); + d.ProcessBlock(inoutBlock); +} + +void DES_EDE_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) +{ + d.ProcessBlock(inBlock, outBlock); + e.ProcessBlock(outBlock); + d.ProcessBlock(outBlock); +} + +void TripleDES_Encryption::ProcessBlock(byte *inoutBlock) +{ + e1.ProcessBlock(inoutBlock); + d.ProcessBlock(inoutBlock); + e2.ProcessBlock(inoutBlock); +} + +void TripleDES_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) +{ + e1.ProcessBlock(inBlock, outBlock); + d.ProcessBlock(outBlock); + e2.ProcessBlock(outBlock); +} + +void TripleDES_Decryption::ProcessBlock(byte *inoutBlock) +{ + d1.ProcessBlock(inoutBlock); + e.ProcessBlock(inoutBlock); + d2.ProcessBlock(inoutBlock); +} + +void TripleDES_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) +{ + d1.ProcessBlock(inBlock, outBlock); + e.ProcessBlock(outBlock); + d2.ProcessBlock(outBlock); +} diff --git a/src/cryptlib/des.h b/src/cryptlib/des.h new file mode 100644 index 0000000..357845a --- /dev/null +++ b/src/cryptlib/des.h @@ -0,0 +1,105 @@ +#ifndef DES_H +#define DES_H + +#include "cryptlib.h" +#include "misc.h" + +class DES : public BlockTransformation +{ +public: + DES(const byte *userKey, CipherDir); + + void ProcessBlock(const byte *inBlock, byte * outBlock); + void ProcessBlock(byte * inoutBlock) + {DES::ProcessBlock(inoutBlock, inoutBlock);} + + enum {KEYLENGTH=8, BLOCKSIZE=8}; + unsigned int BlockSize() const {return BLOCKSIZE;} + +protected: + static const word32 Spbox[8][64]; + + SecBlock k; +}; + +class DESEncryption : public DES +{ +public: + DESEncryption(const byte * userKey) + : DES (userKey, ENCRYPTION) {} +}; + +class DESDecryption : public DES +{ +public: + DESDecryption(const byte * userKey) + : DES (userKey, DECRYPTION) {} +}; + +class DES_EDE_Encryption : public BlockTransformation +{ +public: + DES_EDE_Encryption(const byte * userKey) + : e(userKey, ENCRYPTION), d(userKey + DES::KEYLENGTH, DECRYPTION) {} + + void ProcessBlock(const byte *inBlock, byte * outBlock); + void ProcessBlock(byte * inoutBlock); + + enum {KEYLENGTH=16, BLOCKSIZE=8}; + unsigned int BlockSize() const {return BLOCKSIZE;} + +private: + DES e, d; +}; + +class DES_EDE_Decryption : public BlockTransformation +{ +public: + DES_EDE_Decryption(const byte * userKey) + : d(userKey, DECRYPTION), e(userKey + DES::KEYLENGTH, ENCRYPTION) {} + + void ProcessBlock(const byte *inBlock, byte * outBlock); + void ProcessBlock(byte * inoutBlock); + + enum {KEYLENGTH=16, BLOCKSIZE=8}; + unsigned int BlockSize() const {return BLOCKSIZE;} + +private: + DES d, e; +}; + +class TripleDES_Encryption : public BlockTransformation +{ +public: + TripleDES_Encryption(const byte * userKey) + : e1(userKey, ENCRYPTION), d(userKey + DES::KEYLENGTH, DECRYPTION), + e2(userKey + 2*DES::KEYLENGTH, ENCRYPTION) {} + + void ProcessBlock(const byte *inBlock, byte * outBlock); + void ProcessBlock(byte * inoutBlock); + + enum {KEYLENGTH=24, BLOCKSIZE=8}; + unsigned int BlockSize() const {return BLOCKSIZE;} + +private: + DES e1, d, e2; +}; + +class TripleDES_Decryption : public BlockTransformation +{ +public: + TripleDES_Decryption(const byte * userKey) + : d1(userKey + 2*DES::KEYLENGTH, DECRYPTION), e(userKey + DES::KEYLENGTH, ENCRYPTION), + d2(userKey, DECRYPTION) {} + + void ProcessBlock(const byte *inBlock, byte * outBlock); + void ProcessBlock(byte * inoutBlock); + + enum {KEYLENGTH=24, BLOCKSIZE=8}; + unsigned int BlockSize() const {return BLOCKSIZE;} + +private: + DES d1, e, d2; +}; + +#endif diff --git a/src/cryptlib/dessp.cpp b/src/cryptlib/dessp.cpp new file mode 100644 index 0000000..01aa402 --- /dev/null +++ b/src/cryptlib/dessp.cpp @@ -0,0 +1,79 @@ +// This file is mostly generated by Phil Karn's gensp.c + +#include "pch.h" +#include "des.h" + +const word32 DES::Spbox[8][64] = { +{ +0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, +0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, +0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, +0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, +0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, +0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, +0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, +0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, +{ +0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, +0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, +0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, +0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, +0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, +0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, +0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, +0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, +{ +0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, +0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, +0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, +0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, +0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, +0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, +0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, +0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, +{ +0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, +0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, +0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, +0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, +0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, +0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, +0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, +0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, +{ +0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, +0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, +0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, +0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, +0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, +0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, +0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, +0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, +{ +0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, +0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, +0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, +0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, +0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, +0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, +0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, +0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, +{ +0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, +0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, +0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, +0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, +0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, +0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, +0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, +0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, +{ +0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, +0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, +0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, +0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, +0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, +0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, +0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, +0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} +}; diff --git a/src/cryptlib/elgamal.cpp b/src/cryptlib/elgamal.cpp new file mode 100644 index 0000000..9350869 --- /dev/null +++ b/src/cryptlib/elgamal.cpp @@ -0,0 +1,311 @@ +// elgamal.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "elgamal.h" +#include "asn.h" + +ElGamalCryptoPublicKey::ElGamalCryptoPublicKey(const Integer &p, const Integer &g, const Integer &y) + : p(p), g(g), y(y), modulusLen(p.ByteCount()), + gpc(p, g, ExponentBitLength(), 1), ypc(p, y, ExponentBitLength(), 1) +{ +} + +ElGamalCryptoPublicKey::~ElGamalCryptoPublicKey() +{ + // Note: This empty descrutor was added to get around a SunPro compiler bug. + // Without this destructor, the code core dumped. +} + +ElGamalCryptoPublicKey::ElGamalCryptoPublicKey(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + p.BERDecode(seq); + modulusLen=p.ByteCount(); + g.BERDecode(seq); + y.BERDecode(seq); + gpc.Precompute(p, g, ExponentBitLength(), 1); + ypc.Precompute(p, y, ExponentBitLength(), 1); +} + +void ElGamalCryptoPublicKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + p.DEREncode(seq); + g.DEREncode(seq); + y.DEREncode(seq); +} + +void ElGamalCryptoPublicKey::Precompute(unsigned int precomputationStorage) +{ + gpc.Precompute(p, g, ExponentBitLength(), precomputationStorage); + ypc.Precompute(p, y, ExponentBitLength(), precomputationStorage); +} + +void ElGamalCryptoPublicKey::LoadPrecomputation(BufferedTransformation &bt) +{ + gpc.Load(p, bt); + ypc.Load(p, bt); +} + +void ElGamalCryptoPublicKey::SavePrecomputation(BufferedTransformation &bt) const +{ + gpc.Save(bt); + ypc.Save(bt); +} + +void ElGamalCryptoPublicKey::Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) +{ + assert(plainTextLength <= MaxPlainTextLength()); + + SecByteBlock block(modulusLen-1); + rng.GetBlock(block, modulusLen-2-plainTextLength); + memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength); + block[modulusLen-2] = plainTextLength; + + Integer m(block, modulusLen-1); + Integer a,b; + RawEncrypt(Integer(rng, ExponentBitLength()), m, a, b); + + a.Encode(cipherText, modulusLen); + b.Encode(cipherText+modulusLen, modulusLen); +} + +void ElGamalCryptoPublicKey::RawEncrypt(const Integer &k, const Integer &m, Integer &a, Integer &b) const +{ +// a = a_exp_b_mod_c(g, k, p); +// b = m * a_exp_b_mod_c(y, k, p) % p; + a = gpc.Exponentiate(k); + b = m * ypc.Exponentiate(k) % p; +} + +unsigned int ElGamalCryptoPublicKey::ExponentBitLength() const +{ + return 2*DiscreteLogWorkFactor(p.BitCount()); +} + +// ************************************************************* + +ElGamalCryptoPrivateKey::ElGamalCryptoPrivateKey(const Integer &p, const Integer &g, const Integer &y, const Integer &x) + : ElGamalCryptoPublicKey(p, g, y), x(x) +{ +} + +ElGamalCryptoPrivateKey::ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, unsigned int pbits) +{ + PrimeAndGenerator pg(1, rng, pbits); + p = pg.Prime(); + modulusLen=p.ByteCount(); + g = pg.Generator(); + x.Randomize(rng, ExponentBitLength()); + gpc.Precompute(p, g, ExponentBitLength(), 1); + y = gpc.Exponentiate(x); + ypc.Precompute(p, y, ExponentBitLength(), 1); +} + +ElGamalCryptoPrivateKey::ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, const Integer &pIn, const Integer &gIn) +{ + p = pIn; + modulusLen=p.ByteCount(); + g = gIn; + x.Randomize(rng, ExponentBitLength()); + gpc.Precompute(p, g, ExponentBitLength(), 1); + y = gpc.Exponentiate(x); + ypc.Precompute(p, y, ExponentBitLength(), 1); +} + +ElGamalCryptoPrivateKey::~ElGamalCryptoPrivateKey() +{ + // Note: This empty descrutor was added to get around a SunPro compiler bug. + // Without this destructor, the code core dumped. +} + +ElGamalCryptoPrivateKey::ElGamalCryptoPrivateKey(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + p.BERDecode(seq); + modulusLen=p.ByteCount(); + g.BERDecode(seq); + y.BERDecode(seq); + x.BERDecode(seq); + gpc.Precompute(p, g, ExponentBitLength(), 1); + ypc.Precompute(p, y, ExponentBitLength(), 1); +} + +void ElGamalCryptoPrivateKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + p.DEREncode(seq); + g.DEREncode(seq); + y.DEREncode(seq); + x.DEREncode(seq); +} + +unsigned int ElGamalCryptoPrivateKey::Decrypt(const byte *cipherText, byte *plainText) +{ + Integer a(cipherText, modulusLen); + Integer b(cipherText+modulusLen, modulusLen); + Integer m; + + RawDecrypt(a, b, m); + m.Encode(plainText, 1); + unsigned int plainTextLength = plainText[0]; + if (plainTextLength > MaxPlainTextLength()) + return 0; + m >>= 8; + m.Encode(plainText, plainTextLength); + return plainTextLength; +} + +void ElGamalCryptoPrivateKey::RawDecrypt(const Integer &a, const Integer &b, Integer &m) const +{ + if (x.BitCount()+20 < p.BitCount()) // if x is short + m = b * EuclideanMultiplicativeInverse(a_exp_b_mod_c(a, x, p), p) % p; + else // save a multiplicative inverse calculation + m = b * a_exp_b_mod_c(a, p-1-x, p) % p; +} + +// ****************************************************************** + +ElGamalSigPublicKey::ElGamalSigPublicKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y) + : p(p), q(q), g(g), y(y), qLen(q.ByteCount()), + gpc(p, g, ExponentBitLength(), 1), ypc(p, y, ExponentBitLength(), 1) +{ +} + +ElGamalSigPublicKey::ElGamalSigPublicKey(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + p.BERDecode(seq); + q.BERDecode(seq); + g.BERDecode(seq); + y.BERDecode(seq); + qLen = q.ByteCount(); + gpc.Precompute(p, g, ExponentBitLength(), 1); + ypc.Precompute(p, y, ExponentBitLength(), 1); +} + +void ElGamalSigPublicKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + p.DEREncode(seq); + q.DEREncode(seq); + g.DEREncode(seq); + y.DEREncode(seq); +} + +void ElGamalSigPublicKey::Precompute(unsigned int precomputationStorage) +{ + gpc.Precompute(p, g, ExponentBitLength(), precomputationStorage); + ypc.Precompute(p, y, ExponentBitLength(), precomputationStorage); +} + +void ElGamalSigPublicKey::LoadPrecomputation(BufferedTransformation &bt) +{ + gpc.Load(p, bt); + ypc.Load(p, bt); +} + +void ElGamalSigPublicKey::SavePrecomputation(BufferedTransformation &bt) const +{ + gpc.Save(bt); + ypc.Save(bt); +} + +bool ElGamalSigPublicKey::Verify(const byte *message, unsigned int messageLen, const byte *signature) +{ + assert(messageLen <= MaxMessageLength()); + + Integer m(message, messageLen); + Integer r(signature, qLen); + Integer s(signature+qLen, qLen); + return RawVerify(m, r, s); +} + +bool ElGamalSigPublicKey::RawVerify(const Integer &m, const Integer &r, const Integer &s) const +{ + // check r != 0 && r == (g^s * y^r + m) mod q + return !!r && r == (gpc.CascadeExponentiate(s, ypc, r) + m) % q; +} + +unsigned int ElGamalSigPublicKey::ExponentBitLength() const +{ + return q.BitCount(); +} + +// ************************************************************* + +ElGamalSigPrivateKey::ElGamalSigPrivateKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y, const Integer &x) + : ElGamalSigPublicKey(p, q, g, y), x(x) +{ +} + +ElGamalSigPrivateKey::ElGamalSigPrivateKey(RandomNumberGenerator &rng, unsigned int pbits) +{ + PrimeAndGenerator pg(1, rng, pbits, 2*DiscreteLogWorkFactor(pbits)); + p = pg.Prime(); + q = pg.SubPrime(); + g = pg.Generator(); + x.Randomize(rng, 2, q-2, Integer::ANY); + gpc.Precompute(p, g, ExponentBitLength(), 1); + y = gpc.Exponentiate(x); + ypc.Precompute(p, y, ExponentBitLength(), 1); + qLen = q.ByteCount(); +} + +ElGamalSigPrivateKey::ElGamalSigPrivateKey(RandomNumberGenerator &rng, const Integer &pIn, const Integer &qIn, const Integer &gIn) +{ + p = pIn; + q = qIn; + g = gIn; + x.Randomize(rng, 2, q-2, Integer::ANY); + gpc.Precompute(p, g, ExponentBitLength(), 1); + y = gpc.Exponentiate(x); + ypc.Precompute(p, y, ExponentBitLength(), 1); + qLen = q.ByteCount(); +} + +ElGamalSigPrivateKey::ElGamalSigPrivateKey(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + p.BERDecode(seq); + q.BERDecode(seq); + g.BERDecode(seq); + y.BERDecode(seq); + x.BERDecode(seq); + gpc.Precompute(p, g, ExponentBitLength(), 1); + ypc.Precompute(p, y, ExponentBitLength(), 1); + qLen = q.ByteCount(); +} + +void ElGamalSigPrivateKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + p.DEREncode(seq); + q.DEREncode(seq); + g.DEREncode(seq); + y.DEREncode(seq); + x.DEREncode(seq); +} + +void ElGamalSigPrivateKey::Sign(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) +{ + assert(messageLen <= MaxMessageLength()); + + Integer m(message, messageLen); + Integer r; + Integer s; + + RawSign(rng, m, r, s); + r.Encode(signature, qLen); + s.Encode(signature+qLen, qLen); +} + +void ElGamalSigPrivateKey::RawSign(RandomNumberGenerator &rng, const Integer &m, Integer &r, Integer &s) const +{ + do + { + Integer k(rng, 2, q-2, Integer::ANY); + r = (gpc.Exponentiate(k) + m) % q; + s = (k - x*r) % q; + } while (!r); // make sure r != 0 +} diff --git a/src/cryptlib/elgamal.h b/src/cryptlib/elgamal.h new file mode 100644 index 0000000..583fbf3 --- /dev/null +++ b/src/cryptlib/elgamal.h @@ -0,0 +1,110 @@ +#ifndef ELGAMAL_H +#define ELGAMAL_H + +#include "nbtheory.h" + +class ElGamalCryptoPublicKey : public PK_WithPrecomputation +{ +public: + ElGamalCryptoPublicKey(const Integer &p, const Integer &g, const Integer &y); + ElGamalCryptoPublicKey(BufferedTransformation &bt); + + ~ElGamalCryptoPublicKey(); + + void DEREncode(BufferedTransformation &bt) const; + + void Precompute(unsigned int precomputationStorage=16); + void LoadPrecomputation(BufferedTransformation &storedPrecomputation); + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const; + + void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText); + + unsigned int MaxPlainTextLength() const {return STDMIN(255U, modulusLen-3);} + unsigned int CipherTextLength() const {return 2*modulusLen;} + +protected: + ElGamalCryptoPublicKey() {} + void RawEncrypt(const Integer &k, const Integer &m, Integer &a, Integer &b) const; + unsigned int ExponentBitLength() const; + + Integer p, g, y; + unsigned int modulusLen; + ModExpPrecomputation gpc, ypc; +}; + +class ElGamalCryptoPrivateKey : public ElGamalCryptoPublicKey, public PK_FixedLengthDecryptor +{ +public: + ElGamalCryptoPrivateKey(const Integer &p, const Integer &g, const Integer &y, const Integer &x); + ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, unsigned int pbits); + // generate a random private key, given p and g + ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, const Integer &p, const Integer &g); + + ~ElGamalCryptoPrivateKey(); + + ElGamalCryptoPrivateKey(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + unsigned int Decrypt(const byte *cipherText, byte *plainText); + +protected: + void RawDecrypt(const Integer &a, const Integer &b, Integer &m) const; + + Integer x; +}; + +class ElGamalSigPublicKey : public PK_WithPrecomputation +{ +public: + ElGamalSigPublicKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y); + ElGamalSigPublicKey(BufferedTransformation &bt); + + void DEREncode(BufferedTransformation &bt) const; + + void Precompute(unsigned int precomputationStorage=16); + void LoadPrecomputation(BufferedTransformation &storedPrecomputation); + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const; + + bool Verify(const byte *message, unsigned int messageLen, const byte *signature); + + // message length for signature is unlimited, but only message digests should be signed + unsigned int MaxMessageLength() const {return 0xffff;} + unsigned int SignatureLength() const {return 2*qLen;} + + const Integer& GetPrime() { return p; } + const Integer& GetParameterQ() { return q; } + const Integer& GetParameterG() { return g; } + const Integer& GetParameterY() { return y; } + +protected: + ElGamalSigPublicKey() {} + bool RawVerify(const Integer &m, const Integer &a, const Integer &b) const; + unsigned int ExponentBitLength() const; + + Integer p, q, g, y; + unsigned int qLen; + ModExpPrecomputation gpc, ypc; +}; + +class ElGamalSigPrivateKey : public ElGamalSigPublicKey, public PK_WithPrecomputation +{ +public: + ElGamalSigPrivateKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y, const Integer &x); + ElGamalSigPrivateKey(RandomNumberGenerator &rng, unsigned int pbits); + // generate a random private key, given p and g + ElGamalSigPrivateKey(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g); + + ElGamalSigPrivateKey(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + void Sign(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature); + + const Integer& GetParameterX() { return x; } + +protected: + void RawSign(RandomNumberGenerator &rng, const Integer &m, Integer &a, Integer &b) const; + + Integer x; +}; + +#endif diff --git a/src/cryptlib/eprecomp.cpp b/src/cryptlib/eprecomp.cpp new file mode 100644 index 0000000..c66e3ff --- /dev/null +++ b/src/cryptlib/eprecomp.cpp @@ -0,0 +1,64 @@ +#include "pch.h" +#include "eprecomp.h" +#include "algebra.h" + +#include +USING_NAMESPACE(std) + +template void ExponentiationPrecomputation::Precompute(const Element &base, unsigned int maxExpBits) +{ + assert(storage <= maxExpBits); + exponentBase = Integer::Power2((maxExpBits+storage-1)/storage); + + g[0] = base; + for (unsigned i=1; i typename ExponentiationPrecomputation::Element ExponentiationPrecomputation::Exponentiate(const Integer &exponent) const +{ + vector > eb(storage); // array of segments of the exponent and precalculated bases + Integer temp, e = exponent; + unsigned i; + + for (i=0; i+1(group, eb.begin(), eb.end()); +} + +template typename ExponentiationPrecomputation::Element + ExponentiationPrecomputation::CascadeExponentiate(const Integer &exponent, + const ExponentiationPrecomputation &pc2, const Integer &exponent2) const +{ + vector > eb(storage+pc2.storage); // array of segments of the exponent and precalculated bases + Integer temp, e = exponent; + unsigned i; + + for (i=0; i+1(group, eb.begin(), eb.end()); +} diff --git a/src/cryptlib/eprecomp.h b/src/cryptlib/eprecomp.h new file mode 100644 index 0000000..dbb99c8 --- /dev/null +++ b/src/cryptlib/eprecomp.h @@ -0,0 +1,39 @@ +#ifndef EPRECOMP_H +#define EPRECOMP_H + +#include "integer.h" +#include + +// Please do not directly use the following class. It should be +// considered a private class for the library. The following +// classes are public and use ExponentiationPrecomputation internally. +// +// ModExpPrecomputation; +// EcPrecomputation; +// EcPrecomputation; + +template class ExponentiationPrecomputation +{ +public: + typedef T Group; + typedef typename Group::Element Element; + + ExponentiationPrecomputation(const Group &group) : group(group) {} + + ExponentiationPrecomputation(const Group &group, const Element &base, unsigned int maxExpBits, unsigned int storage) + : group(group), storage(storage), g(storage) {Precompute(base, maxExpBits);} + + ExponentiationPrecomputation(const Group &group, const ExponentiationPrecomputation &pc) + : group(group), storage(pc.storage), exponentBase(pc.exponentBase), g(pc.g) {} + + void Precompute(const Element &base, unsigned int maxExpBits); + Element Exponentiate(const Integer &exponent) const; + Element CascadeExponentiate(const Integer &exponent, const ExponentiationPrecomputation &pc2, const Integer &exponent2) const; + + const Group &group; + unsigned int storage; // number of precalculated bases + Integer exponentBase; // what base to represent the exponent in + std::vector g; // precalculated bases +}; + +#endif diff --git a/src/cryptlib/filters.cpp b/src/cryptlib/filters.cpp new file mode 100644 index 0000000..a542030 --- /dev/null +++ b/src/cryptlib/filters.cpp @@ -0,0 +1,97 @@ +// filters.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "filters.h" +#include "queue.h" +#include + +Filter::Filter(BufferedTransformation *outQ) + : outQueue(outQ ? outQ : new ByteQueue) +{ +} + +Filter::Filter(const Filter &source) + : outQueue(new ByteQueue) +{ +} + +void Filter::Detach(BufferedTransformation *newOut) +{ + std::auto_ptr out(newOut ? newOut : new ByteQueue); + outQueue->Close(); + outQueue->TransferTo(*out); + outQueue.reset(out.release()); +} + +void Filter::Attach(BufferedTransformation *newOut) +{ + if (outQueue->Attachable()) + outQueue->Attach(newOut); + else + Detach(newOut); +} + +BlockFilterBase::BlockFilterBase(BlockTransformation &c, + BufferedTransformation *outQ) + : Filter(outQ), cipher(c), S(cipher.BlockSize()), inBuf(S) +{ + inBufSize=0; +} + +void BlockFilterBase::ProcessBuf() +{ + cipher.ProcessBlock(inBuf); + outQueue->Put(inBuf, S); + inBufSize=0; +} + +void BlockFilterBase::Put(const byte *inString, unsigned int length) +{ + while (length--) + BlockFilterBase::Put(*inString++); +} + +void BlockEncryptionFilter::InputFinished() +{ + if (inBufSize == S) + ProcessBuf(); + // pad last block + memset(inBuf+inBufSize, S-inBufSize, S-inBufSize); + ProcessBuf(); +} + +void BlockDecryptionFilter::InputFinished() +{ + cipher.ProcessBlock(inBuf); + if (inBuf[S-1] > S) + inBuf[S-1] = 0; // something's wrong with the padding + outQueue->Put(inBuf, S-inBuf[S-1]); + inBufSize=0; +} + +void StreamCipherFilter::Put(const byte *inString, unsigned int length) +{ + SecByteBlock temp(length); + cipher.ProcessString(temp, inString, length); + outQueue->Put(temp, length); +} + +void HashFilter::InputFinished() +{ + SecByteBlock buf(hash.DigestSize()); + hash.Final(buf); + outQueue->Put(buf, hash.DigestSize()); +} + +BufferedTransformation *Insert(const byte *in, unsigned int length, BufferedTransformation *outQueue) +{ + outQueue->Put(in, length); + return outQueue; +} + +unsigned int Extract(Source *source, byte *out, unsigned int length) +{ + while (source->MaxRetrieveable() < length && source->Pump(1)); + return source->Get(out, length); +} + diff --git a/src/cryptlib/filters.h b/src/cryptlib/filters.h new file mode 100644 index 0000000..af640cf --- /dev/null +++ b/src/cryptlib/filters.h @@ -0,0 +1,159 @@ +#ifndef FILTERS_H +#define FILTERS_H + +#include "cryptlib.h" +#include "misc.h" +#include "smartptr.h" + +class Filter : public BufferedTransformation +{ +public: + Filter(BufferedTransformation *outQ = NULL); + Filter(const Filter &source); + + bool Attachable() {return true;} + void Detach(BufferedTransformation *newOut = NULL); + void Attach(BufferedTransformation *newOut); + void Close() + {InputFinished(); outQueue->Close();} + + unsigned long MaxRetrieveable() + {return outQueue->MaxRetrieveable();} + + unsigned int Get(byte &outByte) + {return outQueue->Get(outByte);} + unsigned int Get(byte *outString, unsigned int getMax) + {return outQueue->Get(outString, getMax);} + + unsigned int Peek(byte &outByte) const + {return outQueue->Peek(outByte);} + + BufferedTransformation *OutQueue() {return outQueue.get();} + +protected: + member_ptr outQueue; + +private: + void operator=(const Filter &); // assignment not allowed +}; + +class BlockFilterBase : public Filter +{ +public: + BlockFilterBase(BlockTransformation &cipher, + BufferedTransformation *outQueue); + virtual ~BlockFilterBase() {} + + void Put(byte inByte) + { + if (inBufSize == S) + ProcessBuf(); + inBuf[inBufSize++]=inByte; + } + + void Put(const byte *inString, unsigned int length); + +protected: + void ProcessBuf(); + + BlockTransformation &cipher; + const unsigned int S; + SecByteBlock inBuf; + unsigned int inBufSize; +}; + +class BlockEncryptionFilter : public BlockFilterBase +{ +public: + BlockEncryptionFilter(BlockTransformation &cipher, BufferedTransformation *outQueue = NULL) + : BlockFilterBase(cipher, outQueue) {} + +protected: + void InputFinished(); +}; + +class BlockDecryptionFilter : public BlockFilterBase +{ +public: + BlockDecryptionFilter(BlockTransformation &cipher, BufferedTransformation *outQueue = NULL) + : BlockFilterBase(cipher, outQueue) {} + +protected: + void InputFinished(); +}; + +class StreamCipherFilter : public Filter +{ +public: + StreamCipherFilter(StreamCipher &c, + BufferedTransformation *outQueue = NULL) + : Filter(outQueue), cipher(c) {} + + void Put(byte inByte) + {outQueue->Put(cipher.ProcessByte(inByte));} + + void Put(const byte *inString, unsigned int length); + +private: + StreamCipher &cipher; +}; + +class HashFilter : public Filter +{ +public: + HashFilter(HashModule &hm, BufferedTransformation *outQueue = NULL) + : Filter(outQueue), hash(hm) {} + + void InputFinished(); + + void Put(byte inByte) + {hash.Update(&inByte, 1);} + + void Put(const byte *inString, unsigned int length) + {hash.Update(inString, length);} + +private: + HashModule &hash; +}; + +class Source : public Filter +{ +public: + Source(BufferedTransformation *outQ = NULL) + : Filter(outQ) {} + + void Put(byte) + {Pump(1);} + void Put(const byte *, unsigned int length) + {Pump(length);} + void InputFinished() + {PumpAll();} + + virtual unsigned int Pump(unsigned int size) =0; + virtual unsigned long PumpAll() =0; +}; + +class Sink : public BufferedTransformation +{ +public: + unsigned long MaxRetrieveable() + {return 0;} + unsigned int Get(byte &) + {return 0;} + unsigned int Get(byte *, unsigned int) + {return 0;} + unsigned int Peek(byte &) const + {return 0;} +}; + +class BitBucket : public Sink +{ +public: + void Put(byte) {} + void Put(const byte *, unsigned int) {} +}; + +BufferedTransformation *Insert(const byte *in, unsigned int length, BufferedTransformation *outQueue); +unsigned int Extract(Source *source, byte *out, unsigned int length); + +#endif diff --git a/src/cryptlib/forkjoin.cpp b/src/cryptlib/forkjoin.cpp new file mode 100644 index 0000000..2007463 --- /dev/null +++ b/src/cryptlib/forkjoin.cpp @@ -0,0 +1,137 @@ +// forkjoin.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "forkjoin.h" +#include "queue.h" +#include + +Fork::Fork(int n, BufferedTransformation *const *givenOutPorts) + : numberOfPorts(n), outPorts(n) +{ + currentPort = 0; + + for (unsigned int i=0; i out(newOut ? newOut : new ByteQueue); + outPorts[currentPort]->Close(); + outPorts[currentPort]->TransferTo(*out); + outPorts[currentPort].reset(out.release()); +} + +void Fork::Attach(BufferedTransformation *newOut) +{ + if (outPorts[currentPort]->Attachable()) + outPorts[currentPort]->Attach(newOut); + else + Detach(newOut); +} + +void Fork::Close() +{ + InputFinished(); + + for (unsigned int i=0; iClose(); +} + +void Fork::Put(byte inByte) +{ + for (unsigned int i=0; iPut(inByte); +} + +void Fork::Put(const byte *inString, unsigned int length) +{ + for (unsigned int i=0; iPut(inString, length); +} + +// ******************************************************** + +Join::Join(unsigned int n, BufferedTransformation *outQ) + : Filter(outQ), + numberOfPorts(n), + inPorts(n), + interfacesOpen(n), + interfaces(n) +{ + for (unsigned int i=0; iClose(); +} + +// ******************************************************** + +void Interface::Put(byte inByte) +{ + bq.Put(inByte); + parent.NotifyInput(id, 1); +} + +void Interface::Put(const byte *inString, unsigned int length) +{ + bq.Put(inString, length); + parent.NotifyInput(id, length); +} + +unsigned long Interface::MaxRetrieveable() +{ + return parent.MaxRetrieveable(); +} + +void Interface::Close() +{ + parent.NotifyClose(id); +} + +void Interface::Detach(BufferedTransformation *bt) +{ + parent.Detach(bt); +} + +void Interface::Attach(BufferedTransformation *bt) +{ + parent.Attach(bt); +} + +unsigned int Interface::Get(byte &outByte) +{ + return parent.Get(outByte); +} + +unsigned int Interface::Get(byte *outString, unsigned int getMax) +{ + return parent.Get(outString, getMax); +} + +unsigned int Interface::Peek(byte &outByte) const +{ + return parent.Peek(outByte); +} diff --git a/src/cryptlib/forkjoin.h b/src/cryptlib/forkjoin.h new file mode 100644 index 0000000..efe3ae6 --- /dev/null +++ b/src/cryptlib/forkjoin.h @@ -0,0 +1,104 @@ +#ifndef FORKJOIN_H +#define FORKJOIN_H + +#include "cryptlib.h" +#include "filters.h" +#include "queue.h" + +class Fork : public BufferedTransformation +{ +public: + Fork(int number_of_outports, BufferedTransformation *const *outports = NULL); + + void SelectOutPort(int portNumber); + + bool Attachable() {return true;} + void Detach(BufferedTransformation *newOut = NULL); + void Attach(BufferedTransformation *newOut); + virtual void Close(); + + unsigned long MaxRetrieveable() + {return outPorts[currentPort]->MaxRetrieveable();} +// virtual void InputFinished() +// {outPorts[currentPort]->InputFinished();} + + unsigned int Get(byte &outByte) + {return outPorts[currentPort]->Get(outByte);} + unsigned int Get(byte *outString, unsigned int getMax) + {return outPorts[currentPort]->Get(outString, getMax);} + unsigned int Peek(byte &outByte) const + {return outPorts[currentPort]->Peek(outByte);} + + virtual void Put(byte inByte); + virtual void Put(const byte *inString, unsigned int length); + +protected: + unsigned int NumberOfPorts() const {return numberOfPorts;} + BufferedTransformation& AccessPort(unsigned int i) {return *outPorts[i];} + +private: + Fork(const Fork &); // no copying allowed + + unsigned int numberOfPorts, currentPort; + vector_member_ptrs outPorts; +}; + +class Join; + +class Interface : public BufferedTransformation +{ +public: + Interface(Join &p, ByteQueue &b, int i) + : parent(p), bq(b), id(i) {} + + unsigned long MaxRetrieveable(); + void Close(); + bool Attachable() {return true;} + void Detach(BufferedTransformation *bt); + void Attach(BufferedTransformation *bt); + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + unsigned int Get(byte &outByte); + unsigned int Get(byte *outString, unsigned int getMax); + unsigned int Peek(byte &outByte) const; + +private: + Join &parent; + ByteQueue &bq; + const int id; +}; + +class Join : public Filter +{ +public: + Join(unsigned int number_of_inports, BufferedTransformation *outQ = NULL); + + // Note that ReleaseInterface is similar but not completely compatible + // with SelectInterface of version 2.0. ReleaseInterface can be called + // only once for each interface, and if an interface is released, + // the caller will be responsible for deleting it. + Interface *ReleaseInterface(unsigned int i); + + virtual void NotifyInput(unsigned int interfaceId, unsigned int length); + virtual void NotifyClose(unsigned int interfaceId); + + void Put(byte inByte) {outQueue->Put(inByte);} + void Put(const byte *inString, unsigned int length) + {outQueue->Put(inString, length);} + +protected: + unsigned int NumberOfPorts() const {return numberOfPorts;} + ByteQueue& AccessPort(unsigned int i) {return *inPorts[i];} + unsigned int InterfacesOpen() const {return interfacesOpen;} + +private: + Join(const Join &); // no copying allowed + + unsigned int numberOfPorts; + vector_member_ptrs inPorts; + unsigned int interfacesOpen; + vector_member_ptrs interfaces; +}; + +#endif diff --git a/src/cryptlib/integer.cpp b/src/cryptlib/integer.cpp new file mode 100644 index 0000000..e7f4f15 --- /dev/null +++ b/src/cryptlib/integer.cpp @@ -0,0 +1,2362 @@ +// integer.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "integer.h" +#include "modarith.h" +#include "nbtheory.h" +#include "asn.h" +#include "words.h" + +#include "iostream" +//USING_NAMESPACE(std) + +#include "algebra.cpp" +#include "eprecomp.cpp" + +#define MAKE_DWORD(lowWord, highWord) ((dword(highWord)< B[N]) + return 1; + else if (A[N] < B[N]) + return -1; + + return 0; +} + +static word Increment(word *A, unsigned int N, word B=1) +{ + assert(N); + word t = A[0]; + A[0] = t+B; + if (A[0] >= t) + return 0; + for (unsigned i=1; i= A0) + if (B0 >= B1) + { + s = 0; + d.dw = (dword)(A1-A0)*(B0-B1); + } + else + { + s = (A1-A0); + d.dw = (dword)s*(word)(B0-B1); + } + else + if (B0 > B1) + { + s = (B0-B1); + d.dw = (word)(A1-A0)*(dword)s; + } + else + { + s = 0; + d.dw = (dword)(A0-A1)*(B1-B0); + } + + dword_union A0B0; + A0B0.dw = (dword)A0*B0; + C[0] = A0B0.low; + + dword_union A1B1; + A1B1.dw = (dword)A1*B1; + dword_union t; + t.dw = (dword)A0B0.high + A0B0.low + d.low + A1B1.low; + C[1] = t.low; + + t.dw = A1B1.dw + t.high + A0B0.high + d.high + A1B1.high - s; + C[2] = t.low; + C[3] = t.high; +} + +static word AtomicMultiplyAdd(word *C, word A0, word A1, word B0, word B1) +{ + word s; + dword_union d; + + if (A1 >= A0) + if (B0 >= B1) + { + s = 0; + d.dw = (dword)(A1-A0)*(B0-B1); + } + else + { + s = (A1-A0); + d.dw = (dword)s*(word)(B0-B1); + } + else + if (B0 > B1) + { + s = (B0-B1); + d.dw = (word)(A1-A0)*(dword)s; + } + else + { + s = 0; + d.dw = (dword)(A0-A1)*(B1-B0); + } + + dword_union A0B0; + A0B0.dw = (dword)A0*B0; + dword_union t; + t.dw = A0B0.dw + C[0]; + C[0] = t.low; + + dword_union A1B1; + A1B1.dw = (dword)A1*B1; + t.dw = (dword) t.high + A0B0.low + d.low + A1B1.low + C[1]; + C[1] = t.low; + + t.dw = (dword) t.high + A1B1.low + A0B0.high + d.high + A1B1.high - s + C[2]; + C[2] = t.low; + + t.dw = (dword) t.high + A1B1.high + C[3]; + C[3] = t.low; + return t.high; +} + +static inline void AtomicSquare(word *C, word A, word B) +{ +#ifdef _MSC_VER + // VC50 workaround + AtomicMultiply(C, A, B, A, B); +#else + dword_union t1; + t1.dw = (dword) A*A; + C[0] = t1.low; + + dword_union t2; + t2.dw = (dword) A*B; + t1.dw = (dword) t1.high + t2.low + t2.low; + C[1] = t1.low; + + t1.dw = (dword) B*B + t1.high + t2.high + t2.high; + C[2] = t1.low; + C[3] = t1.high; +#endif +} + +static inline void AtomicMultiplyBottom(word *C, word A0, word A1, word B0, word B1) +{ + dword_union t; + t.dw = (dword)A0*B0; + C[0] = t.low; + C[1] = t.high + A0*B1 + A1*B0; +} + +static inline void AtomicMultiplyBottomAdd(word *C, word A0, word A1, word B0, word B1) +{ + dword_union t; + t.dw = (dword)A0*B0 + C[0]; + C[0] = t.low; + C[1] += t.high + A0*B1 + A1*B0; +} + +static void CombaMultiply(word *R, const word *A, const word *B) +{ + dword_union p; + word c=0, d=0, e=0; + +#define MulAcc(x, y) \ + p.dw = (dword)A[x] * B[y] + c; \ + c = p.low; \ + p.dw = (dword)d + p.high; \ + d = p.low; \ + e += p.high; + +#define SaveMulAcc(s, x, y) \ + R[s] = c; \ + p.dw = (dword)A[x] * B[y] + d; \ + c = p.low; \ + p.dw = (dword)e + p.high; \ + d = p.low; \ + e = p.high; + + p.dw = (dword)A[0] * B[0]; + R[0] = p.low; + c = p.high; + d = e = 0; + + MulAcc(0, 1); + MulAcc(1, 0); + + SaveMulAcc(1, 2, 0); + MulAcc(1, 1); + MulAcc(0, 2); + + SaveMulAcc(2, 0, 3); + MulAcc(1, 2); + MulAcc(2, 1); + MulAcc(3, 0); + + SaveMulAcc(3, 3, 1); + MulAcc(2, 2); + MulAcc(1, 3); + + SaveMulAcc(4, 2, 3); + MulAcc(3, 2); + + R[5] = c; + p.dw = (dword)A[3] * B[3] + d; + R[6] = p.low; + R[7] = e + p.high; + +#undef MulAcc +#undef SaveMulAcc +} + +static void AtomicInverseModPower2(word *C, word A0, word A1) +{ + assert(A0%2==1); + + const dword A = MAKE_DWORD(A0, A1); + dword_union R; + R.dw = A0%8; + + for (unsigned i=3; i<2*WORD_BITS; i*=2) + R.dw = R.dw*(2-R.dw*A); + + assert(R.dw*A==1); + + C[0] = R.low; + C[1] = R.high; +} + +// ******************************************************** + +#define A0 A +#define A1 (A+N2) +#define B0 B +#define B1 (B+N2) + +#define T0 T +#define T1 (T+N2) +#define T2 (T+N) +#define T3 (T+N+N2) + +#define R0 R +#define R1 (R+N2) +#define R2 (R+N) +#define R3 (R+N+N2) + +// R[2*N] - result = A*B +// T[2*N] - temporary work space +// A[N] --- multiplier +// B[N] --- multiplicant + +void RecursiveMultiply(word *R, word *T, const word *A, const word *B, unsigned int N) +{ + assert(N>=2 && N%2==0); + + if (N==2) + AtomicMultiply(R, A[0], A[1], B[0], B[1]); + else if (N==4) + CombaMultiply(R, A, B); + else + { + const unsigned int N2 = N/2; + int carry; + + int aComp = Compare(A0, A1, N2); + int bComp = Compare(B0, B1, N2); + + switch (2*aComp + aComp + bComp) + { + case -4: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + Subtract(T1, T1, R0, N2); + carry = -1; + break; + case -2: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 2: + Subtract(R0, A0, A1, N2); + Subtract(R1, B1, B0, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 4: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + Subtract(T1, T1, R1, N2); + carry = -1; + break; + default: + SetWords(T0, 0, N); + carry = 0; + } + + RecursiveMultiply(R0, T2, A0, B0, N2); + RecursiveMultiply(R2, T2, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1 + + carry += Add(T0, T0, R0, N); + carry += Add(T0, T0, R2, N); + carry += Add(R1, R1, T0, N); + + assert (carry >= 0 && carry <= 2); + Increment(R3, N2, carry); + } +} + +// R[2*N] - result = A*A +// T[2*N] - temporary work space +// A[N] --- number to be squared + +void RecursiveSquare(word *R, word *T, const word *A, unsigned int N) +{ + assert(N && N%2==0); + + if (N==2) + AtomicSquare(R, A[0], A[1]); + else if (N==4) + { + AtomicSquare(R, A[0], A[1]); + AtomicSquare(R+4, A[2], A[3]); + AtomicMultiply(T, A[0], A[1], A[2], A[3]); + word carry = Add(R+2, R+2, T, 4); + carry += Add(R+2, R+2, T, 4); + Increment(R+6, 2, carry); + } + else + { + const unsigned int N2 = N/2; + + RecursiveSquare(R0, T2, A0, N2); + RecursiveSquare(R2, T2, A1, N2); + RecursiveMultiply(T0, T2, A0, A1, N2); + + word carry = Add(R1, R1, T0, N); + carry += Add(R1, R1, T0, N); + Increment(R3, N2, carry); + } +} + +// R[N] - bottom half of A*B +// T[N] - temporary work space +// A[N] - multiplier +// B[N] - multiplicant + +void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, unsigned int N) +{ + assert(N>=2 && N%2==0); + + if (N==2) + AtomicMultiplyBottom(R, A[0], A[1], B[0], B[1]); + else if (N==4) + { + AtomicMultiply(R, A[0], A[1], B[0], B[1]); + AtomicMultiplyBottomAdd(R+2, A[0], A[1], B[2], B[3]); + AtomicMultiplyBottomAdd(R+2, A[2], A[3], B[0], B[1]); + } + else + { + const unsigned int N2 = N/2; + + RecursiveMultiply(R, T, A0, B0, N2); + RecursiveMultiplyBottom(T0, T1, A1, B0, N2); + Add(R1, R1, T0, N2); + RecursiveMultiplyBottom(T0, T1, A0, B1, N2); + Add(R1, R1, T0, N2); + } +} + +// R[N] --- upper half of A*B +// T[2*N] - temporary work space +// L[N] --- lower half of A*B +// A[N] --- multiplier +// B[N] --- multiplicant + +void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, unsigned int N) +{ + assert(N>=2 && N%2==0); + + if (N==2) + { + AtomicMultiply(T, A[0], A[1], B[0], B[1]); + R[0] = T[2]; + R[1] = T[3]; + } + else + { + const unsigned int N2 = N/2; + int carry; + + int aComp = Compare(A0, A1, N2); + int bComp = Compare(B0, B1, N2); + + switch (2*aComp + aComp + bComp) + { + case -4: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + Subtract(T1, T1, R0, N2); + carry = -1; + break; + case -2: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 2: + Subtract(R0, A0, A1, N2); + Subtract(R1, B1, B0, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 4: + Subtract(R0, A1, A0, N2); + Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + Subtract(T1, T1, R1, N2); + carry = -1; + break; + default: + SetWords(T0, 0, N); + carry = 0; + } + + RecursiveMultiply(T2, R0, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1 + + CopyWords(R0, L+N2, N2); + word c2 = Subtract(R0, R0, L, N2); + c2 += Subtract(R0, R0, T0, N2); + word t = (Compare(R0, T2, N2) == -1); + + carry += t; + carry += Increment(R0, N2, c2+t); + carry += Add(R0, R0, T1, N2); + carry += Add(R0, R0, T3, N2); + + CopyWords(R1, T3, N2); + assert (carry >= 0 && carry <= 2); + Increment(R1, N2, carry); + } +} + +// R[NA+NB] - result = A*B +// T[NA+NB] - temporary work space +// A[NA] ---- multiplier +// B[NB] ---- multiplicant + +void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA, const word *B, unsigned int NB) +{ + if (NA == NB) + { + if (A == B) + RecursiveSquare(R, T, A, NA); + else + RecursiveMultiply(R, T, A, B, NA); + + return; + } + + if (NA > NB) + { + swap(A, B); + swap(NA, NB); + } + + assert(NB % NA == 0); + assert((NB/NA)%2 == 0); // NB is an even multiple of NA + + if (NA==2 && !A[1]) + { + switch (A[0]) + { + case 0: + SetWords(R, 0, NB+2); + return; + case 1: + CopyWords(R, B, NB); + R[NB] = R[NB+1] = 0; + return; + default: + R[NB] = LinearMultiply(R, B, A[0], NB); + R[NB+1] = 0; + return; + } + } + + RecursiveMultiply(R, T, A, B, NA); + CopyWords(T+2*NA, R+NA, NA); + + unsigned i; + + for (i=2*NA; i=4); + +#define M0 M +#define M1 (M+N2) +#define V0 V +#define V1 (V+N2) + +#define X0 X +#define X1 (X+N2) +#define X2 (X+N) +#define X3 (X+N+N2) + + const unsigned int N2 = N/2; + RecursiveMultiply(T0, T2, V0, X3, N2); + int c2 = Add(T0, T0, X0, N); + RecursiveMultiplyBottom(T3, T2, T0, U, N2); + RecursiveMultiplyTop(T2, R, T0, T3, M0, N2); + c2 -= Subtract(T2, T1, T2, N2); + RecursiveMultiply(T0, R, T3, M1, N2); + c2 -= Subtract(T0, T2, T0, N2); + int c3 = -(int)Subtract(T1, X2, T1, N2); + RecursiveMultiply(R0, T2, V1, X3, N2); + c3 += Add(R, R, T, N); + + if (c2>0) + c3 += Increment(R1, N2); + else if (c2<0) + c3 -= Decrement(R1, N2, -c2); + + assert(c3>=-1 && c3<=1); + if (c3>0) + Subtract(R, R, M, N); + else if (c3<0) + Add(R, R, M, N); + +#undef M0 +#undef M1 +#undef V0 +#undef V1 + +#undef X0 +#undef X1 +#undef X2 +#undef X3 +} + +#undef A0 +#undef A1 +#undef B0 +#undef B1 + +#undef T0 +#undef T1 +#undef T2 +#undef T3 + +#undef R0 +#undef R1 +#undef R2 +#undef R3 + +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +static word SubatomicDivide(word *A, word B0, word B1) +{ + // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word + assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); + + dword_union p, u; + word Q; + + // estimate the quotient: do a 2 word by 1 word divide + if (B1+1 == 0) + Q = A[2]; + else + Q = word(MAKE_DWORD(A[1], A[2]) / (B1+1)); + + // now subtract Q*B from A + p.dw = (dword) B0*Q; + u.dw = (dword) A[0] - p.low; + A[0] = u.low; + u.dw = (dword) A[1] - p.high - (word)(0-u.high) - (dword)B1*Q; + A[1] = u.low; + A[2] += u.high; + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u.dw = (dword) A[0] - B0; + A[0] = u.low; + u.dw = (dword) A[1] - B1 - (word)(0-u.high); + A[1] = u.low; + A[2] += u.high; + Q++; + assert(Q); // shouldn't overflow + } + + return Q; +} + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +static inline void AtomicDivide(word &Q0, word &Q1, const word *A, word B0, word B1) +{ + if (!B0 && !B1) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + { + Q0 = A[2]; + Q1 = A[3]; + } + else + { + word T[4]; + T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3]; + Q1 = SubatomicDivide(T+1, B0, B1); + Q0 = SubatomicDivide(T, B0, B1); + +#ifdef DEBUG + // multiply quotient and divisor and add remainder, make sure it equals dividend + assert(!T[2] && !T[3] && (T[1] < B1 || (T[1]==B1 && T[0]= 0) + { + R[N] -= Subtract(R, R, B, N); + Q1 += (++Q0==0); + assert(Q0 || Q1); // no overflow + } +} + +// R[NB] -------- remainder = A%B +// Q[NA-NB+2] --- quotient = A/B +// T[NA+2*NB+4] - temp work space +// A[NA] -------- dividend +// B[NB] -------- divisor + +void Divide(word *R, word *Q, word *T, const word *A, unsigned int NA, const word *B, unsigned int NB) +{ + assert(NA && NB && NA%2==0 && NB%2==0); + assert(B[NB-1] || B[NB-2]); + assert(NB <= NA); + + // set up temporary work space + word *const TA=T; + word *const TB=T+NA+2; + word *const TP=T+NA+2+NB; + + // copy B into TB and normalize it so that TB has highest bit set to 1 + unsigned shiftWords = (B[NB-1]==0); + TB[0] = TB[NB-1] = 0; + CopyWords(TB+shiftWords, B, NB-shiftWords); + unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); + assert(shiftBits < WORD_BITS); + ShiftWordsLeftByBits(TB, NB, shiftBits); + + // copy A into TA and normalize it + TA[0] = TA[NA] = TA[NA+1] = 0; + CopyWords(TA+shiftWords, A, NA); + ShiftWordsLeftByBits(TA, NA+2, shiftBits); + + if (TA[NA+1]==0 && TA[NA] <= 1) + { + Q[NA-NB+1] = Q[NA-NB] = 0; + while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) + { + TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); + ++Q[NA-NB]; + } + } + else + { + NA+=2; + assert(Compare(TA+NA-NB, TB, NB) < 0); + } + + word B0 = TB[NB-2] + 1; + word B1 = TB[NB-1] + (B0==0); + + // start reducing TA mod TB, 2 words at a time + for (unsigned i=NA-2; i>=NB; i-=2) + { + AtomicDivide(Q[i-NB], Q[i-NB+1], TA+i-2, B0, B1); + CorrectQuotientEstimate(TA+i-NB, TP, Q[i-NB], Q[i-NB+1], TB, NB); + } + + // copy TA into R, and denormalize it + CopyWords(R, TA+shiftWords, NB); + ShiftWordsRightByBits(R, NB, shiftBits); +} + +static inline unsigned int EvenWordCount(const word *X, unsigned int N) +{ + while (N && X[N-2]==0 && X[N-1]==0) + N-=2; + return N; +} + +// return k +// R[N] --- result = A^(-1) * 2^k mod M +// T[4*N] - temporary work space +// A[NA] -- number to take inverse of +// M[N] --- modulus + +unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, const word *M, unsigned int N) +{ + assert(NA<=N && N && N%2==0); + + word *b = T; + word *c = T+N; + word *f = T+2*N; + word *g = T+3*N; + unsigned int bcLen=2, fgLen=EvenWordCount(M, N); + unsigned int k=0, s=0; + + SetWords(T, 0, 3*N); + b[0]=1; + CopyWords(f, A, NA); + CopyWords(g, M, N); + + while (1) + { + word t=f[0]; + while (!t) + { + if (EvenWordCount(f, fgLen)==0) + { + SetWords(R, 0, N); + return 0; + } + + ShiftWordsRightByWords(f, fgLen, 1); + if (c[bcLen-1]) bcLen+=2; + assert(bcLen <= N); + ShiftWordsLeftByWords(c, bcLen, 1); + k+=WORD_BITS; + t=f[0]; + } + + unsigned int i=0; + while (t%2 == 0) + { + t>>=1; + i++; + } + k+=i; + + if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2) + { + if (s%2==0) + CopyWords(R, b, N); + else + Subtract(R, M, b, N); + return k; + } + + ShiftWordsRightByBits(f, fgLen, i); + t=ShiftWordsLeftByBits(c, bcLen, i); + if (t) + { + c[bcLen] = t; + bcLen+=2; + assert(bcLen <= N); + } + + if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) + fgLen-=2; + + if (Compare(f, g, fgLen)==-1) + { + swap(f, g); + swap(b, c); + s++; + } + + Subtract(f, f, g, fgLen); + + if (Add(b, b, c, bcLen)) + { + b[bcLen] = 1; + bcLen+=2; + assert(bcLen <= N); + } + } +} + +// R[N] - result = A/(2^k) mod M +// A[N] - input +// M[N] - modulus + +void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M, unsigned int N) +{ + CopyWords(R, A, N); + + while (k--) + { + if (R[0]%2==0) + ShiftWordsRightByBits(R, N, 1); + else + { + word carry = Add(R, R, M, N); + ShiftWordsRightByBits(R, N, 1); + R[N-1] += carry<<(WORD_BITS-1); + } + } +} + +// R[N] - result = A*(2^k) mod M +// A[N] - input +// M[N] - modulus + +void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M, unsigned int N) +{ + CopyWords(R, A, N); + + while (k--) + if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) + Subtract(R, R, M, N); +} + +// ****************************************************************** + +static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; + +inline unsigned int RoundupSize(unsigned int n) +{ + if (n<=8) + return RoundupSizeTable[n]; + else if (n<=16) + return 16; + else if (n<=32) + return 32; + else if (n<=64) + return 64; + else return 1U << BitPrecision(n-1); +} + +Integer::Integer() + : reg(2), sign(POSITIVE) +{ + reg[(unsigned int)0] = reg[(unsigned int)1] = 0; +} + +Integer::Integer(const Integer& t) + : reg(RoundupSize(t.WordCount())), sign(t.sign) +{ + CopyWords(reg, t.reg, reg.size); +} + +Integer::Integer(long value) + : reg(2) +{ + if (value >= 0) + sign = POSITIVE; + else + { + sign = NEGATIVE; + value = -value; + } + reg[(unsigned int)0] = word(value); +#ifdef __GNUC__ + reg[(unsigned int)1] = 0; +#else + reg[(unsigned int)1] = sizeof(value)>WORD_SIZE ? word(value>>WORD_BITS) : 0; +#endif +} + +long Integer::ConvertToLong() const +{ + unsigned long value = reg[(unsigned int)0]; +#ifndef __GNUC__ + value += sizeof(value)>WORD_SIZE ? ((unsigned long)reg[1]<= reg.size) + return 0; + else + return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); +} + +void Integer::SetBit(unsigned int n, bool value) +{ + if (value) + { + reg.CleanGrow(RoundupSize(bitsToWords(n+1))); + reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); + } + else + { + if (n/WORD_BITS < reg.size) + reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); + } +} + +byte Integer::GetByte(unsigned int n) const +{ + if (n/WORD_SIZE >= reg.size) + return 0; + else + return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); +} + +void Integer::SetByte(unsigned int n, byte value) +{ + reg.CleanGrow(RoundupSize(bytesToWords(n+1))); + reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + +Integer Integer::operator-() const +{ + Integer result(*this); + result.Negate(); + return result; +} + +Integer Integer::AbsoluteValue() const +{ + Integer result(*this); + result.sign = POSITIVE; + return result; +} + +void swap(Integer &a, Integer &b) +{ + swap(a.reg, b.reg); + swap(a.sign, b.sign); +} + +Integer::Integer(word value, unsigned int length) + : reg(RoundupSize(length)), sign(POSITIVE) +{ + reg[(unsigned int)0] = value; + SetWords(reg+(unsigned int)1, 0, reg.size-(unsigned int)1); +} + + +Integer::Integer(const char *str) + : reg(2), sign(POSITIVE) +{ + word radix; + unsigned length = strlen(str); + + SetWords(reg, 0, 2); + + if (length == 0) + return; + + switch (str[length-1]) + { + case 'h': + case 'H': + radix=16; + break; + case 'o': + case 'O': + radix=8; + break; + case 'b': + case 'B': + radix=2; + break; + default: + radix=10; + } + + for (unsigned i=0; i= '0' && str[i] <= '9') + digit = str[i] - '0'; + else if (str[i] >= 'A' && str[i] <= 'F') + digit = str[i] - 'A' + 10; + else if (str[i] >= 'a' && str[i] <= 'f') + digit = str[i] - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + *this *= radix; + *this += digit; + } + } + + if (str[0] == '-') + Negate(); +} + +unsigned int Integer::WordCount() const +{ + return CountWords(reg, reg.size); +} + +unsigned int Integer::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int Integer::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); + else + return 0; +} + +void Integer::Decode(const byte *input, unsigned int inputLen, Signedness s) +{ + sign = ((s==SIGNED) && (input[0] & 0x80)) ? NEGATIVE : POSITIVE; + + while (input[0]==0 && inputLen>0) + { + input++; + inputLen--; + } + + reg.CleanNew(RoundupSize(bytesToWords(inputLen))); + + for (unsigned i=0; i 2) + BERDecodeError(); + bc = *input++; + if (lengthBytes > 1) + bc = (bc << 8) | *input++; + } + Decode(input, bc, SIGNED); +} + +void Integer::BERDecode(BufferedTransformation &bt) +{ + byte b; + if (!bt.Get(b) || b != INTEGER) + BERDecodeError(); + + unsigned int bc; + BERLengthDecode(bt, bc); + + SecByteBlock buf(bc); + + if (bc != bt.Get(buf, bc)) + BERDecodeError(); + Decode(buf, bc, SIGNED); +} + +void Integer::Randomize(RandomNumberGenerator &rng, unsigned int nbits) +{ + const unsigned int nbytes = nbits/8 + 1; + SecByteBlock buf(nbytes); + rng.GetBlock(buf, nbytes); + buf[(unsigned int)0] = (byte)Crop(buf[(unsigned int)0], nbits % 8); + Decode(buf, nbytes, UNSIGNED); +} + +void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) +{ + assert(max > min); + + Integer range = max - min; + const unsigned int nbits = range.BitCount(); + + do + { + Randomize(rng, nbits); + } + while (*this > range); + + *this += min; +} + +void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType) +{ + while (1) // loop until a suitable rn has been generated + { + Randomize(rng, min, max); + + switch (rnType) + { + case ANY: + return; + + case ODD: + reg[(unsigned int)0] |= 1; + if (*this <= max) + return; + else + break; + + case PRIME: + case BLUMINT: + if (NextPrime(*this, max, rnType==BLUMINT)) + return; + else + break; + + default: + assert(false); + } + } +} + +std::istream& operator>>(std::istream& in, Integer &a) +{ + char c; + unsigned int length = 0; + SecBlock str(length + 16); + + ws(in); + + do + { + in.read(&c, 1); + str[length++] = c; + if (length >= str.size) + str.Grow(length + 16); + } + while (in && (c=='-' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.')); + + if (in.gcount()) + in.putback(c); + str[length-1] = '\0'; + a = Integer(str); + + return in; +} + +ostream& operator<<(ostream& out, const Integer &a) +{ + // Get relevant conversion specifications from ostream. + long f = out.flags() & ios::basefield; // Get base digits. + int base, block; + char suffix; + switch(f) + { + case ios::oct : + base = 8; + block = 8; + suffix = 'o'; + break; + case ios::hex : + base = 16; + block = 4; + suffix = 'h'; + break; + default : + base = 10; + block = 3; + suffix = '.'; + } + + SecBlock s(a.BitCount() / (BitPrecision(base)-1) + 1); + Integer temp1=a, temp2; + unsigned i=0; + const char vec[]="0123456789ABCDEF"; + + if (a.IsNegative()) + { + out << '-'; + temp1.Negate(); + } + + if (!a) + out << '0'; + + while (!!temp1) + { + s[i++]=vec[Integer::ShortDivide(temp2, temp1, base)]; + temp1=temp2; + } + + while (i--) + { + out << s[i]; + if (i && !(i%block)) + out << ","; + } + return out << suffix; +} + +Integer& Integer::operator++() +{ + if (NotNegative()) + { + if (Increment(reg, reg.size)) + { + reg.CleanGrow(2*reg.size); + reg[reg.size/2]=1; + } + } + else + { + word borrow = Decrement(reg, reg.size); + assert(!borrow); + if (WordCount()==0) + *this = Zero(); + } + return *this; +} + +Integer& Integer::operator--() +{ + if (IsNegative()) + { + if (Increment(reg, reg.size)) + { + reg.CleanGrow(2*reg.size); + reg[reg.size/2]=1; + } + } + else + { + if (Decrement(reg, reg.size)) + *this = -One(); + } + return *this; +} + +void PositiveAdd(Integer &sum, const Integer &a, const Integer& b) +{ + word carry; + if (a.reg.size == b.reg.size) + carry = Add(sum.reg, a.reg, b.reg, a.reg.size); + else if (a.reg.size > b.reg.size) + { + carry = Add(sum.reg, a.reg, b.reg, b.reg.size); + CopyWords(sum.reg+b.reg.size, a.reg+b.reg.size, a.reg.size-b.reg.size); + carry = Increment(sum.reg+b.reg.size, a.reg.size-b.reg.size, carry); + } + else + { + carry = Add(sum.reg, a.reg, b.reg, a.reg.size); + CopyWords(sum.reg+a.reg.size, b.reg+a.reg.size, b.reg.size-a.reg.size); + carry = Increment(sum.reg+a.reg.size, b.reg.size-a.reg.size, carry); + } + + if (carry) + { + sum.reg.CleanGrow(2*sum.reg.size); + sum.reg[sum.reg.size/2] = 1; + } + sum.sign = Integer::POSITIVE; +} + +void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) +{ + unsigned aSize = a.WordCount(); + aSize += aSize%2; + unsigned bSize = b.WordCount(); + bSize += bSize%2; + + if (aSize == bSize) + { + if (Compare(a.reg, b.reg, aSize) >= 0) + { + Subtract(diff.reg, a.reg, b.reg, aSize); + diff.sign = Integer::POSITIVE; + } + else + { + Subtract(diff.reg, b.reg, a.reg, aSize); + diff.sign = Integer::NEGATIVE; + } + } + else if (aSize > bSize) + { + word borrow = Subtract(diff.reg, a.reg, b.reg, bSize); + CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize); + borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow); + assert(!borrow); + diff.sign = Integer::POSITIVE; + } + else + { + word borrow = Subtract(diff.reg, b.reg, a.reg, aSize); + CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize); + borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow); + assert(!borrow); + diff.sign = Integer::NEGATIVE; + } +} + +Integer operator+(const Integer &a, const Integer& b) +{ + Integer sum((word)0, STDMAX(a.reg.size, b.reg.size)); + if (a.NotNegative()) + { + if (b.NotNegative()) + PositiveAdd(sum, a, b); + else + PositiveSubtract(sum, a, b); + } + else + { + if (b.NotNegative()) + PositiveSubtract(sum, b, a); + else + { + PositiveAdd(sum, a, b); + sum.sign = Integer::NEGATIVE; + } + } + return sum; +} + +Integer& Integer::operator+=(const Integer& t) +{ + reg.CleanGrow(t.reg.size); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveAdd(*this, *this, t); + else + PositiveSubtract(*this, *this, t); + } + else + { + if (t.NotNegative()) + PositiveSubtract(*this, t, *this); + else + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + } + return *this; +} + +Integer operator-(const Integer &a, const Integer& b) +{ + Integer diff((word)0, STDMAX(a.reg.size, b.reg.size)); + if (a.NotNegative()) + { + if (b.NotNegative()) + PositiveSubtract(diff, a, b); + else + PositiveAdd(diff, a, b); + } + else + { + if (b.NotNegative()) + { + PositiveAdd(diff, a, b); + diff.sign = Integer::NEGATIVE; + } + else + PositiveSubtract(diff, b, a); + } + return diff; +} + +Integer& Integer::operator-=(const Integer& t) +{ + reg.CleanGrow(t.reg.size); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveSubtract(*this, *this, t); + else + PositiveAdd(*this, *this, t); + } + else + { + if (t.NotNegative()) + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + else + PositiveSubtract(*this, t, *this); + } + return *this; +} + +Integer& Integer::operator<<=(unsigned int n) +{ + const unsigned int wordCount = WordCount(); + const unsigned int shiftWords = n / WORD_BITS; + const unsigned int shiftBits = n % WORD_BITS; + + reg.CleanGrow(RoundupSize(wordCount+bitsToWords(n))); + ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords); + ShiftWordsLeftByBits(reg+shiftWords, wordCount+bitsToWords(shiftBits), shiftBits); + return *this; +} + +Integer& Integer::operator>>=(unsigned int n) +{ + const unsigned int wordCount = WordCount(); + const unsigned int shiftWords = n / WORD_BITS; + const unsigned int shiftBits = n % WORD_BITS; + + ShiftWordsRightByWords(reg, wordCount, shiftWords); + if (wordCount > shiftWords) + ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits); + if (IsNegative() && WordCount()==0) // avoid -0 + *this = Zero(); + return *this; +} + +void PositiveMultiply(Integer &product, const Integer &a, const Integer &b) +{ + unsigned aSize = RoundupSize(a.WordCount()); + unsigned bSize = RoundupSize(b.WordCount()); + + product.reg.CleanNew(RoundupSize(aSize+bSize)); + product.sign = Integer::POSITIVE; + + SecWordBlock workspace(aSize + bSize); + AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize); +} + +void Multiply(Integer &product, const Integer &a, const Integer &b) +{ + PositiveMultiply(product, a, b); + + if (a.NotNegative() != b.NotNegative()) + product.Negate(); +} + +Integer operator*(const Integer &a, const Integer &b) +{ + Integer product; + Multiply(product, a, b); + return product; +} + +/* +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer ÷nd, const Integer &divisor) +{ + remainder.reg.CleanNew(divisor.reg.size); + remainder.sign = Integer::POSITIVE; + quotient.reg.New(0); + quotient.sign = Integer::POSITIVE; + unsigned i=dividend.BitCount(); + while (i--) + { + word overflow = ShiftWordsLeftByBits(remainder.reg, remainder.reg.size, 1); + remainder.reg[0] |= dividend[i]; + if (overflow || remainder >= divisor) + { + Subtract(remainder.reg, remainder.reg, divisor.reg, remainder.reg.size); + quotient.SetBit(i); + } + } +} +*/ + +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer &a, const Integer &b) +{ + unsigned aSize = a.WordCount(); + unsigned bSize = b.WordCount(); + + if (!bSize) + { +#ifdef THROW_EXCEPTIONS + throw Integer::DivideByZero(); +#else + return; +#endif + } + + if (a.PositiveCompare(b) == -1) + { + remainder = a; + remainder.sign = Integer::POSITIVE; + quotient = Integer::Zero(); + return; + } + + aSize += aSize%2; // round up to next even number + bSize += bSize%2; + + remainder.reg.CleanNew(RoundupSize(bSize)); + remainder.sign = Integer::POSITIVE; + quotient.reg.CleanNew(RoundupSize(aSize-bSize+2)); + quotient.sign = Integer::POSITIVE; + + SecWordBlock T(aSize+2*bSize+4); + Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize); +} + +void Integer::Divide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor) +{ + PositiveDivide(remainder, quotient, dividend, divisor); + + if (dividend.IsNegative()) + { + quotient.Negate(); + if (!!remainder) + { + --quotient; + remainder = divisor.AbsoluteValue() - remainder; + } + } + + if (divisor.IsNegative()) + quotient.Negate(); +} + +Integer operator/(const Integer &a, const Integer &b) +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, a, b); + return quotient; +} + +Integer operator%(const Integer &a, const Integer &b) +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, a, b); + return remainder; +} + +word Integer::ShortDivide(Integer "ient, const Integer ÷nd, word divisor) +{ +#ifdef THROW_EXCEPTIONS + if (!divisor) + throw Integer::DivideByZero(); +#endif + + assert(divisor); + + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + { + quotient = dividend >> (BitPrecision(divisor)-1); + return dividend.reg[(unsigned int)0] & (divisor-1); + } + + unsigned int i = dividend.WordCount(); + quotient.reg.CleanNew(RoundupSize(i)); + word remainder = 0; + while (i--) + { + quotient.reg[i] = word(MAKE_DWORD(dividend.reg[i], remainder) / divisor); + remainder = word(MAKE_DWORD(dividend.reg[i], remainder) % divisor); + } + + if (dividend.NotNegative()) + quotient.sign = POSITIVE; + else + { + quotient.sign = NEGATIVE; + if (remainder) + { + --quotient; + remainder = divisor - remainder; + } + } + + return remainder; +} + +Integer operator/(const Integer &a, word b) +{ + Integer quotient; + Integer::ShortDivide(quotient, a, b); + return quotient; +} + +word operator%(const Integer ÷nd, word divisor) +{ +#ifdef THROW_EXCEPTIONS + if (!divisor) + throw Integer::DivideByZero(); +#endif + + assert(divisor); + + word remainder; + + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + remainder = dividend.reg[(unsigned int)0] & (divisor-1); + else + { + unsigned int i = dividend.WordCount(); + + if (divisor <= 5) + { + dword sum=0; + while (i--) + sum += dividend.reg[i]; + remainder = word(sum%divisor); + } + else + { + remainder = 0; + while (i--) + remainder = word(MAKE_DWORD(dividend.reg[i], remainder) % divisor); + } + } + + if (dividend.IsNegative() && remainder) + remainder = divisor - remainder; + + return remainder; +} + +void Integer::Negate() +{ + if (!!(*this)) // don't flip sign if *this==0 + sign = Sign(1-sign); +} + +int Integer::PositiveCompare(const Integer& t) const +{ + unsigned size = WordCount(), tSize = t.WordCount(); + + if (size == tSize) + return ::Compare(reg, t.reg, size); + else + return size > tSize ? 1 : -1; +} + +int Integer::Compare(const Integer& t) const +{ + if (NotNegative()) + { + if (t.NotNegative()) + return PositiveCompare(t); + else + return 1; + } + else + { + if (t.NotNegative()) + return -1; + else + return -PositiveCompare(t); + } +} + +Integer Integer::SquareRoot() const +{ + // overestimate square root + Integer x, y = Power2((BitCount()+1)/2); + assert(y*y >= *this); + + do + { + x = y; + y = (x + *this/x) >> 1; + } while (y().Gcd(a, b); +} + +Integer Integer::InverseMod(const Integer &m) const +{ + assert(m.NotNegative()); + + if (IsNegative() || *this>=m) + return (*this%m).InverseMod(m); + + if (m.IsEven()) + { + if (!m || IsEven()) + return Zero(); // no inverse + if (*this == One()) + return One(); + + Integer u = m.InverseMod(*this); + return !u ? Zero() : (m*(*this-u)+1)/(*this); + } + + SecBlock T(m.reg.size * 4); + Integer r((word)0, m.reg.size); + unsigned k = AlmostInverse(r.reg, T, reg, reg.size, m.reg, m.reg.size); + DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size); + return r; +} + +// ******************************************************** + +Integer ModularArithmetic::Add(const Integer &a, const Integer &b) const +{ + if (a.reg.size==modulus.reg.size && b.reg.size==modulus.reg.size) + { + if (::Add(result.reg.ptr, a.reg, b.reg, a.reg.size) + || Compare(result.reg, modulus.reg, a.reg.size) >= 0) + { + ::Subtract(result.reg.ptr, result.reg, modulus.reg, a.reg.size); + } + return result; + } + else + {Integer r=a+b; if (r>=modulus) r-=modulus; return r;} +} + +Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const +{ + if (a.reg.size==modulus.reg.size && b.reg.size==modulus.reg.size) + { + if (::Add(a.reg, a.reg, b.reg, a.reg.size) + || Compare(a.reg, modulus.reg, a.reg.size) >= 0) + { + ::Subtract(a.reg, a.reg, modulus.reg, a.reg.size); + } + } + else + {a+=b; if (a>=modulus) a-=modulus;} + + return a; +} + +Integer ModularArithmetic::Subtract(const Integer &a, const Integer &b) const +{ + if (a.reg.size==modulus.reg.size && b.reg.size==modulus.reg.size) + { + if (::Subtract(result.reg.ptr, a.reg, b.reg, a.reg.size)) + ::Add(result.reg.ptr, result.reg, modulus.reg, a.reg.size); + return result; + } + else + return Add(a, Inverse(b)); +} + +Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const +{ + if (a.reg.size==modulus.reg.size && b.reg.size==modulus.reg.size) + { + if (::Subtract(a.reg, a.reg, b.reg, a.reg.size)) + ::Add(a.reg, a.reg, modulus.reg, a.reg.size); + } + else + Accumulate(a, Inverse(b)); + + return a; +} + +Integer ModularArithmetic::Inverse(const Integer &a) const +{ + if (!a) + return a; + + CopyWords(result.reg.ptr, modulus.reg, modulus.reg.size); + if (::Subtract(result.reg.ptr, result.reg, a.reg, a.reg.size)) + Decrement(result.reg.ptr+a.reg.size, 1, modulus.reg.size-a.reg.size); + + return result; +} + +Integer ModularArithmetic::MultiplicativeInverse(const Integer &a) const +{ + return a.InverseMod(modulus); +} + +Integer ModularArithmetic::Exponentiate(const Integer &a, const Integer &e) const +{ + if (modulus.IsOdd()) + { + MontgomeryRepresentation dr(modulus); + return dr.ConvertOut(dr.Exponentiate(dr.ConvertIn(a), e)); + } + else + return AbstractRing::Exponentiate(a, e); +} + +Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const +{ + if (modulus.IsOdd()) + { + MontgomeryRepresentation dr(modulus); + return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2)); + } + else + return AbstractRing::CascadeExponentiate(x, e1, y, e2); +} + +MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd + : ModularArithmetic(m), + u((word)0, modulus.reg.size), + workspace(5*modulus.reg.size) +{ + assert(modulus.IsOdd()); + RecursiveInverseModPower2(u.reg, workspace, modulus.reg, modulus.reg.size); +} + +Integer MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const +{ + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N && b.reg.size<=N); + + AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size, b.reg, b.reg.size); + SetWords(T+a.reg.size+b.reg.size, 0, 2*N-a.reg.size-b.reg.size); + MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); + return result; +} + +Integer MontgomeryRepresentation::Square(const Integer &a) const +{ + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N); + + RecursiveSquare(T, T+2*N, a.reg, a.reg.size); + SetWords(T+2*a.reg.size, 0, 2*N-2*a.reg.size); + MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); + return result; +} + +Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const +{ + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N); + + CopyWords(T, a.reg, a.reg.size); + SetWords(T+a.reg.size, 0, 2*N-a.reg.size); + MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); + return result; +} + +Integer MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const +{ +// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size))%modulus; + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N); + + CopyWords(T, a.reg, a.reg.size); + SetWords(T+a.reg.size, 0, 2*N-a.reg.size); + MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); + unsigned k = AlmostInverse(R, T, R, N, modulus.reg, N); + +// cout << "k=" << k << " N*32=" << 32*N << endl; + + if (k>N*WORD_BITS) + DivideByPower2Mod(R, R, k-N*WORD_BITS, modulus.reg, N); + else + MultiplyByPower2Mod(R, R, N*WORD_BITS-k, modulus.reg, N); + + return result; +} + +HalfMontgomeryRepresentation::HalfMontgomeryRepresentation(const Integer &m) // modulus must be odd + : ModularArithmetic(m), + v((modulus.reg.CleanGrow(4), Integer::Power2(3*WORD_BITS*modulus.reg.size/2)%modulus)), + u((word)0, modulus.reg.size/2), + workspace(4*modulus.reg.size) +{ + assert(modulus.IsOdd()); + + result.reg.Grow(4); + v.reg.CleanGrow(modulus.reg.size); + RecursiveInverseModPower2(u.reg, workspace, modulus.reg, modulus.reg.size/2); +} + +Integer HalfMontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const +{ + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N && b.reg.size<=N); + + AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size, b.reg, b.reg.size); + SetWords(T+a.reg.size+b.reg.size, 0, 2*N-a.reg.size-b.reg.size); + HalfMontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, v.reg, N); + return result; +} + +Integer HalfMontgomeryRepresentation::Square(const Integer &a) const +{ + word *const T = workspace.ptr; + const unsigned int N = modulus.reg.size; + word *const R = result.reg.ptr; + assert(a.reg.size<=N); + + RecursiveSquare(T, T+2*N, a.reg, a.reg.size); + SetWords(T+2*a.reg.size, 0, 2*N-2*a.reg.size); + HalfMontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, v.reg, N); + return result; +} + +Integer HalfMontgomeryRepresentation::ConvertOut(const Integer &a) const +{ + word *const T = workspace.ptr; + word *const R = result.reg.ptr; + const unsigned int N = modulus.reg.size; + assert(a.reg.size<=N); + + CopyWords(T, a.reg, a.reg.size); + SetWords(T+a.reg.size, 0, 2*N-a.reg.size); + HalfMontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, v.reg, N); + return result; +} + +Integer HalfMontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const +{ + return (a.InverseMod(modulus)<<(WORD_BITS*modulus.reg.size))%modulus; +} diff --git a/src/cryptlib/integer.h b/src/cryptlib/integer.h new file mode 100644 index 0000000..1754336 --- /dev/null +++ b/src/cryptlib/integer.h @@ -0,0 +1,319 @@ +#ifndef INTEGER_H +#define INTEGER_H + +#include "cryptlib.h" +#include "misc.h" + +#include "iosfwd" + +class Integer; +Integer operator+(const Integer &a, const Integer &b); + +/// multiple precision integer and basic arithmetics +/** This class can represent positive and negative integers + with absolute value less than 2**(8 * sizeof(word) * 2**sizeof(int)). +*/ +class Integer +{ +public: + //@Man: ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + /// division by zero exception + class DivideByZero : public CryptlibException + { + public: + DivideByZero() : CryptlibException("Integer: division by zero") {} + }; + + /// + enum Signedness { + /// + UNSIGNED, + /// + SIGNED}; + + /// + enum RandomNumberType { + /// + ANY, + /// + ODD, + /// + PRIME, + /// not actually a Blum integer, but rather a prime that is 3 mod 4 + BLUMINT}; + //@} + + //@Man: CREATORS + //@{ + /// creates the zero integer + Integer(); + + /// copy constructor + Integer(const Integer& t); + + /// convert from long + Integer(long value); + + /// convert from string + /** str can be in base 2, 8, 10, or 16. Base is determined by a + case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. + */ + Integer(const char *str); + + /// convert from big-endian byte array + Integer(const byte *encodedInteger, unsigned int byteCount, Signedness s=UNSIGNED); + + /// convert from Basic Encoding Rules encoded byte array + Integer(const byte *BEREncodedInteger); + + /// convert from BER encoded byte array stored in a BufferedTransformation object + Integer(BufferedTransformation &bt); + + /// create a random integer + /** The random integer created is uniformly distributed over [0, 2**bitcount). */ + Integer(RandomNumberGenerator &rng, unsigned int bitcount); + + /// create a random integer of special type + /** Ideally, the random integer created should be uniformly distributed + over {x | min <= x <= max and x is of rnType}. However the actual + distribution may not uniform because sequential search is used to + find an appropriate number from a random starting point. + */ + Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY); + + /// create the integer 2**e + static Integer Power2(unsigned int e); + + /// avoid calling constructors for these frequently used integers + static const Integer &Zero(); + /// + static const Integer &One(); + //@} + + //@Man: ACCESSORS + //@{ + /// return equivalent signed long if possible, otherwise undefined + long ConvertToLong() const; + + /// minimum number of bytes to encode this integer + /** MinEncodedSize of 0 is 1 */ + unsigned int MinEncodedSize(Signedness=UNSIGNED) const; + /// encode in big-endian format + /** unsigned means ignore sign, signed means use two's complement. + if outputLen < MinEncodedSize, the most significant bytes will be dropped + if outputLen > MinEncodedSize, the most significant bytes will be padded + */ + unsigned int Encode(byte *output, unsigned int outputLen, Signedness=UNSIGNED) const; + + /// encode integer using Distinguished Encoding Rules, returns size of output + unsigned int DEREncode(byte *output) const; + /// encode using DER, put result into a BufferedTransformation object + unsigned int DEREncode(BufferedTransformation &bt) const; + + /// number of significant bits = floor(log2(abs(*this))) - 1 + unsigned int BitCount() const; + /// number of significant bytes = ceiling(BitCount()/8) + unsigned int ByteCount() const; + /// number of significant words = ceiling(ByteCount()/sizeof(word)) + unsigned int WordCount() const; + + /// return the n-th bit, n=0 being the least significant bit + bool GetBit(unsigned int n) const; + /// return the n-th byte + byte GetByte(unsigned int n) const; + + /// + bool IsNegative() const {return sign == NEGATIVE;} + /// + bool NotNegative() const {return sign == POSITIVE;} + /// + bool IsPositive() const {return sign == POSITIVE && !!*this;} + /// + bool IsEven() const {return GetBit(0) == 0;} + /// + bool IsOdd() const {return GetBit(0) == 1;} + //@} + + //@Man: MANIPULATORS + //@{ + /// + Integer& operator=(const Integer& t); + + /// + Integer& operator+=(const Integer& t); + /// + Integer& operator-=(const Integer& t); + /// + Integer& operator*=(const Integer& t) {return *this = *this*t;} + /// + Integer& operator/=(const Integer& t) {return *this = *this/t;} + /// + Integer& operator%=(const Integer& t) {return *this = *this%t;} + /// + Integer& operator/=(word t) {return *this = *this/t;} + /// + Integer& operator%=(word t) {return *this = *this%t;} + + /// + Integer& operator<<=(unsigned int); + /// + Integer& operator>>=(unsigned int); + + /// + void Decode(const byte *input, unsigned int inputLen, Signedness=UNSIGNED); + + /// + void BERDecode(const byte *input); + /// + void BERDecode(BufferedTransformation &bt); + + /// + void Randomize(RandomNumberGenerator &rng, unsigned int bitcount); + /// + void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max); + /// + void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType); + + /// set the n-th bit to value + void SetBit(unsigned int n, bool value=1); + /// set the n-th byte to value + void SetByte(unsigned int n, byte value); + + /// + void Negate(); + /// + void SetPositive() {sign = POSITIVE;} + /// + void SetNegative() {if (!!(*this)) sign = NEGATIVE;} + + /// + friend void swap(Integer &a, Integer &b); + //@} + + //@Man: UNARY OPERATORS + //@{ + /// + bool operator!() const; + /// + Integer operator+() const {return *this;} + /// + Integer operator-() const; + /// + Integer& operator++(); + /// + Integer& operator--(); + /// + Integer operator++(int) {Integer temp = *this; ++*this; return temp;} + /// + Integer operator--(int) {Integer temp = *this; --*this; return temp;} + //@} + + //@Man: BINARY OPERATORS + //@{ + /// + friend Integer operator+(const Integer &a, const Integer &b); + /// + friend Integer operator-(const Integer &a, const Integer &b); + /// + friend Integer operator*(const Integer &a, const Integer &b); + /// + friend Integer operator/(const Integer &a, const Integer &b); + /// + friend Integer operator%(const Integer &a, const Integer &b); + /// + friend Integer operator/(const Integer &a, word b); + /// + friend word operator%(const Integer &a, word b); + + /// + Integer operator>>(unsigned int n) const {return Integer(*this)>>=n;} + /// + Integer operator<<(unsigned int n) const {return Integer(*this)<<=n;} + + /// + friend bool operator==(const Integer& a, const Integer& b) {return (a.Compare(b)==0);} + /// + friend bool operator!=(const Integer& a, const Integer& b) {return (a.Compare(b)!=0);} + /// + friend bool operator> (const Integer& a, const Integer& b) {return (a.Compare(b)> 0);} + /// + friend bool operator>=(const Integer& a, const Integer& b) {return (a.Compare(b)>=0);} + /// + friend bool operator< (const Integer& a, const Integer& b) {return (a.Compare(b)< 0);} + /// + friend bool operator<=(const Integer& a, const Integer& b) {return (a.Compare(b)<=0);} + //@} + + //@Man: OTHER ARITHMETIC FUNCTIONS + //@{ + /// signed comparison + /** returns: + \begin{itemize} + \item -1 if *this < a + \item 0 if *this = a + \item 1 if *this > a + \end{itemize} + */ + int Compare(const Integer& a) const; + + /// + Integer AbsoluteValue() const; + /// + Integer Doubled() const {return *this + *this;} + /// + Integer Squared() const {return *this * (*this);} + /// extract square root, return floor of square root if not perfect square + Integer SquareRoot() const; + /// return whether this integer is a perfect square + bool IsSquare() const; + + /// is 1 or -1 + bool IsUnit() const; + /// return inverse if 1 or -1, otherwise return 0 + Integer MultiplicativeInverse() const; + + /// modular multiplication + friend Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m); + /// modular exponentiation + friend Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m); + + /// calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) + static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d); + /// use a faster division algorithm when divisor is short + static word ShortDivide(Integer &q, const Integer &a, word d); + + /// greatest common divisor + static Integer Gcd(const Integer &a, const Integer &n); + /// calculate multiplicative inverse of *this mod n + Integer InverseMod(const Integer &n) const; + //@} + + //@Man: INPUT/OUTPUT + //@{ + /// + friend std::istream& operator>>(std::istream& in, Integer &a); + /// + friend std::ostream& operator<<(std::ostream& out, const Integer &a); + //@} + +private: + friend class ModularArithmetic; + friend class MontgomeryRepresentation; + friend class HalfMontgomeryRepresentation; + + Integer(word value, unsigned int length); + + int PositiveCompare(const Integer &t) const; + friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b); + friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b); + friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b); + friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor); + + enum Sign {POSITIVE=0, NEGATIVE=1}; + + SecWordBlock reg; + Sign sign; +}; + +#endif diff --git a/src/cryptlib/iterhash.cpp b/src/cryptlib/iterhash.cpp new file mode 100644 index 0000000..bc83db8 --- /dev/null +++ b/src/cryptlib/iterhash.cpp @@ -0,0 +1,11 @@ +// iterhash.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "iterhash.h" + +#ifdef WORD64_AVAILABLE +template<> class IteratedHash; +#endif + +template<> class IteratedHash; + diff --git a/src/cryptlib/iterhash.h b/src/cryptlib/iterhash.h new file mode 100644 index 0000000..00c006a --- /dev/null +++ b/src/cryptlib/iterhash.h @@ -0,0 +1,113 @@ +#ifndef ITERHASH_H +#define ITERHASH_H + +#include "cryptlib.h" +#include "misc.h" + +/* The following classes are explicitly instantiated in iterhash.cpp + + IteratedHash + IteratedHash // #ifdef WORD64_AVAILABLE +*/ + +template class IteratedHash : public virtual HashModule +{ +public: + IteratedHash(unsigned int blockSize, unsigned int digestSize); + ~IteratedHash(); + void Update(const byte *input, unsigned int length); + + typedef T HashWordType; + +protected: + void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); + virtual void Init() =0; + virtual void HashBlock(const T *input) =0; + + unsigned int blockSize; + word32 countLo, countHi; // 64-bit bit count + SecBlock data; // Data buffer + SecBlock digest; // Message digest +}; + +template IteratedHash::IteratedHash(unsigned int blockSize, unsigned int digestSize) + : blockSize(blockSize), data(blockSize/sizeof(T)), digest(digestSize/sizeof(T)) +{ +} + +template IteratedHash::~IteratedHash() +{ +} + +template void IteratedHash::Update(const byte *input, unsigned int len) +{ + word32 tmp = countLo; + if ((countLo = tmp + ((word32)len << 3)) < tmp) + countHi++; // Carry from low to high + countHi += len >> 29; + + assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2 + unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1); + + if (num != 0) + { + if ((num+len) >= blockSize) + { + memcpy((byte *)data.ptr+num, input, blockSize-num); + HashBlock(data); + input += (blockSize-num); + len-=(blockSize - num); + num=0; + // drop through and do the rest + } + else + { + memcpy((byte *)data.ptr+num, input, len); + return; + } + } + + // we now can process the input data in blocks of blockSize + // chars and save the leftovers to this->data. + if (len >= blockSize) + { + if ((ptr_size_type)input % sizeof(T)) // test for alignment + do + { // copy input first if it's not aligned correctly + memcpy(data, input, blockSize); + HashBlock(data); + input+=blockSize; + len-=blockSize; + } while (len >= blockSize); + else + do + { + HashBlock((T *)input); + input+=blockSize; + len-=blockSize; + } while (len >= blockSize); + } + + memcpy(data, input, len); +} + +template void IteratedHash::PadLastBlock(unsigned int lastBlockSize, byte padFirst) +{ + unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1); + assert(num < blockSize); + ((byte *)data.ptr)[num++]=padFirst; + if (num <= lastBlockSize) + memset((byte *)data.ptr+num, 0, lastBlockSize-num); + else + { + memset((byte *)data.ptr+num, 0, blockSize-num); + HashBlock(data); + memset(data, 0, lastBlockSize); + } +} + +// provide empty definitions to avoid instantiation warnings +//template void IteratedHash::Init() {} +//template void IteratedHash::HashBlock(const T *input) {} + +#endif diff --git a/src/cryptlib/license.txt b/src/cryptlib/license.txt new file mode 100644 index 0000000..90ba8f0 --- /dev/null +++ b/src/cryptlib/license.txt @@ -0,0 +1,53 @@ +Compilation Copyright (c) 1995-1998 by Wei Dai. All rights reserved. +This copyright applies only to this particular software distribution +package, and does not imply a copyright on any particular module in +the library. + +All modules in this library except the following are dedicated to +the public domain by Wei Dai. + +The following modules are copyrighted by their respective original authors. + +md5.cpp md5mac.cpp - Copyright 1995 Eric Young. +sha.cpp - Copyright 1992 Peter Gutmann. +cast.cpp - Copyright 1996 Peter Gutmann. +idea.cpp - Copyright 1992 Colin Plumb. +haval.cpp - Copyright 1992 Yuliang Zheng. +zbits.cpp ztrees.cpp zdeflate.cpp - Copyright 1990-1992 Mark Adler, + Richard B. Wales, Jean-loup Gailly. + + +Permission to use, copy, modify, and distribute this compilation for +any purpose is hereby granted without fee, subject to +the following license: + +1. Any copy or modification of this compilation must include the above +copyright notice and this license. + +2. Users of the software included in this compilation agree to use +their best efforts to provide Wei Dai with any modifications containing +improvements or extensions and hereby grant Wei Dai a perpetual, +royalty-free license to use and distribute such modifications under +the terms of this license. + +3. Wei Dai makes no warranty or representation that the operation of the +software in this compilation will be error-free, and Wei Dai is under no +obligation to provide any services, by way of maintenance, update, or +otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS" +WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR +DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +4. Users will not use Wei Dai or any other contributor's name in any +publicity or advertising, without prior written consent in each case. + +5. Export of this software from the United States may require a +specific license from the United States Government. It is the +responsibility of any person or organization contemplating export +to obtain such a license before exporting. + +6. Certain parts of this software may be protected by patents. It +is the users' responsibility to obtain the appropriate +licenses before using those parts. diff --git a/src/cryptlib/misc.cpp b/src/cryptlib/misc.cpp new file mode 100644 index 0000000..78afdc5 --- /dev/null +++ b/src/cryptlib/misc.cpp @@ -0,0 +1,72 @@ +// misc.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "misc.h" +#include "words.h" + +void xorbuf(byte *buf, const byte *mask, unsigned int count) +{ + if (((ptr_size_type)buf | (ptr_size_type)mask | count) % WORD_SIZE == 0) + XorWords((word *)buf, (const word *)mask, count/WORD_SIZE); + else + { + for (unsigned int i=0; i0; i/=2) + value ^= value >> i; + return (unsigned int)value&1; +} + +unsigned int BytePrecision(unsigned long value) +{ + unsigned int i; + for (i=sizeof(value); i; --i) + if (value >> (i-1)*8) + break; + + return i; +} + +unsigned int BitPrecision(unsigned long value) +{ + if (!value) + return 0; + + unsigned int l=0, h=8*sizeof(value); + + while (h-l > 1) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h; +} + +unsigned long Crop(unsigned long value, int size) +{ + if (size < 8*(int)sizeof(value)) + return (value & ((1L << size) - 1)); + else + return value; +} + diff --git a/src/cryptlib/misc.h b/src/cryptlib/misc.h new file mode 100644 index 0000000..6d4c949 --- /dev/null +++ b/src/cryptlib/misc.h @@ -0,0 +1,258 @@ +#ifndef MISC_H +#define MISC_H + +#include "config.h" +#include +#include +#include + +inline unsigned int bitsToBytes(unsigned int bitCount) +{ + return ((bitCount+7)/(8)); +} + +inline unsigned int bytesToWords(unsigned int byteCount) +{ + return ((byteCount+WORD_SIZE-1)/WORD_SIZE); +} + +inline unsigned int bitsToWords(unsigned int bitCount) +{ + return ((bitCount+WORD_BITS-1)/(WORD_BITS)); +} + +void xorbuf(byte *buf, const byte *mask, unsigned int count); +void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count); + +template inline T rotl(T x, unsigned int y) +{ + return ((x<>(sizeof(T)*8-y))); +} + +template inline T rotr(T x, unsigned int y) +{ + return ((x>>y) | (x<<(sizeof(T)*8-y))); +} + +#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + +#include +#define FAST_ROTATE + +template<> inline unsigned short rotl(unsigned short x, unsigned int y) +{ + return (unsigned short)((x<>(16-y))); +} + +template<> inline unsigned short rotr(unsigned short x, unsigned int y) +{ + return (unsigned short)((x>>y) | (x<<(16-y))); +} + +template<> inline unsigned long rotl(unsigned long x, unsigned int y) +{ + return _lrotl(x, y); +} + +template<> inline unsigned long rotr(unsigned long x, unsigned int y) +{ + return _lrotr(x, y); +} +#endif // defined(_MSC_VER) || defined(__BCPLUSPLUS__) + +inline word16 byteReverse(word16 value) +{ + return rotl(value, 8U); +} + +inline word32 byteReverse(word32 value) +{ +#ifdef FAST_ROTATE + // 5 instructions with rotate instruction, 9 without + return (rotr(value, 8) & 0xff00ff00) | (rotl(value, 8) & 0x00ff00ff); +#elif defined(_KCC) + // 6 instructions with rotate instruction, 8 without + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return ((value<<16U) | (value>>16U)); +#else + // 6 instructions with rotate instruction, 8 without + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotl(value, 16U); +#endif +} + +#ifdef WORD64_AVAILABLE +inline word64 byteReverse(word64 value) +{ + value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); + value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); +#ifdef _KCC + return ((value<<32U) | (value>>32U)); +#else + return rotl(value, 32U); +#endif +} +#endif + +template void byteReverse(T *out, const T *in, unsigned int byteCount) +{ + assert(byteCount%sizeof(T) == 0); + byteCount /= sizeof(T); + for (unsigned i=0; i>(8*(y)))&255) +#endif + +unsigned int Parity(unsigned long); +unsigned int BytePrecision(unsigned long); +unsigned int BitPrecision(unsigned long); +unsigned long Crop(unsigned long, int size); + +// ******************************************************** + +#ifdef SECALLOC_DEFAULT +#define SecAlloc(type, number) (new type[(number)]) +#define SecFree(ptr, number) (memset((ptr), 0, (number)*sizeof(*(ptr))), delete [] (ptr)) +#else +#define SecAlloc(type, number) (new type[(number)]) +#define SecFree(ptr, number) (delete [] (ptr)) +#endif + +template struct SecBlock +{ + SecBlock(unsigned int size=0) + : size(size) {ptr = SecAlloc(T, size); memset(ptr, 0, size*sizeof(T));} + SecBlock(const SecBlock &t) + : size(t.size) {ptr = SecAlloc(T, size); CopyFrom(t);} + SecBlock(const T *t, unsigned int size) + : size(size) {ptr = SecAlloc(T, size); memcpy(ptr, t, size*sizeof(T));} + ~SecBlock() + {SecFree(ptr, size);} + +#if defined(__GNUC__) || defined(__BCPLUSPLUS__) + operator const void *() const + {return ptr;} + operator void *() + {return ptr;} +#endif + + operator const T *() const + {return ptr;} + operator T *() + {return ptr;} + +#if !defined(_MSC_VER) && !defined(_KCC) + T *operator +(unsigned int offset) + {return ptr+offset;} + const T *operator +(unsigned int offset) const + {return ptr+offset;} + T *operator +(long offset) + {return ptr+offset;} + const T *operator +(long offset) const + {return ptr+offset;} + T& operator[](unsigned int index) + {assert(index &t) + { + New(t.size); + memcpy(ptr, t.ptr, size*sizeof(T)); + } + + SecBlock& operator=(const SecBlock &t) + { + CopyFrom(t); + return *this; + } + + bool operator==(const SecBlock &t) const + { + return size == t.size && memcmp(ptr, t.ptr, size*sizeof(T)) == 0; + } + + void New(unsigned int newSize) + { + if (newSize != size) + { + T *newPtr = SecAlloc(T, newSize); + SecFree(ptr, size); + ptr = newPtr; + size = newSize; + } + } + + void CleanNew(unsigned int newSize) + { + if (newSize != size) + { + T *newPtr = SecAlloc(T, newSize); + SecFree(ptr, size); + ptr = newPtr; + size = newSize; + } + memset(ptr, 0, size*sizeof(T)); + } + + void Grow(unsigned int newSize) + { + if (newSize > size) + { + T *newPtr = SecAlloc(T, newSize); + memcpy(newPtr, ptr, size*sizeof(T)); + SecFree(ptr, size); + ptr = newPtr; + size = newSize; + } + } + + void CleanGrow(unsigned int newSize) + { + if (newSize > size) + { + T *newPtr = SecAlloc(T, newSize); + memcpy(newPtr, ptr, size*sizeof(T)); + memset(newPtr+size, 0, (newSize-size)*sizeof(T)); + SecFree(ptr, size); + ptr = newPtr; + size = newSize; + } + } + + void swap(SecBlock &b); + friend void swap(SecBlock &a, SecBlock &b) {a.swap(b);} + + unsigned int size; + T *ptr; +}; + +template void SecBlock::swap(SecBlock &b) +{ + std::swap(size, b.size); + std::swap(ptr, b.ptr); +} + +typedef SecBlock SecByteBlock; +typedef SecBlock SecWordBlock; + +#endif // MISC_H diff --git a/src/cryptlib/modarith.h b/src/cryptlib/modarith.h new file mode 100644 index 0000000..cf1ca26 --- /dev/null +++ b/src/cryptlib/modarith.h @@ -0,0 +1,153 @@ +#ifndef MODARITH_H +#define MODARITH_H + +// implementations are in integer.cpp + +#include "cryptlib.h" +#include "misc.h" +#include "integer.h" +#include "algebra.h" + +class ModularArithmetic : public AbstractRing +{ +public: + ModularArithmetic(const Integer &modulus) + : modulus(modulus), result((word)0, modulus.reg.size) {} + + ModularArithmetic(const ModularArithmetic &ma) + : modulus(ma.modulus), result((word)0, modulus.reg.size) {} + + const Integer& GetModulus() const {return modulus;} + + virtual Integer ConvertIn(const Integer &a) const + {return a%modulus;} + + virtual Integer ConvertOut(const Integer &a) const + {return a;} + + bool Equal(const Integer &a, const Integer &b) const + {return a==b;} + + Integer Zero() const + {return Integer::Zero();} + + Integer Add(const Integer &a, const Integer &b) const; + + Integer& Accumulate(Integer &a, const Integer &b) const; + + Integer Inverse(const Integer &a) const; + + Integer Subtract(const Integer &a, const Integer &b) const; + + Integer& Reduce(Integer &a, const Integer &b) const; + + Integer Double(const Integer &a) const + {return Add(a, a);} + + virtual Integer One() const + {return Integer::One();} + + virtual Integer Multiply(const Integer &a, const Integer &b) const + {return a*b%modulus;} + + virtual Integer Square(const Integer &a) const + {return a.Squared()%modulus;} + + virtual bool IsUnit(const Integer &a) const + {return Integer::Gcd(a, modulus).IsUnit();} + + virtual Integer MultiplicativeInverse(const Integer &a) const; + + Integer Divide(const Integer &a, const Integer &b) const + {return Multiply(a, MultiplicativeInverse(b));} + + virtual Integer Exponentiate(const Integer &a, const Integer &e) const; + + virtual Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const; + + unsigned int MaxElementBitLength() const + {return (modulus-1).BitCount();} + + unsigned int MaxElementByteLength() const + {return (modulus-1).ByteCount();} + +protected: + Integer modulus, result; +}; + +// do modular arithmetics in Montgomery representation for increased speed +class MontgomeryRepresentation : public ModularArithmetic +{ +public: + MontgomeryRepresentation(const Integer &modulus); // modulus must be odd + + Integer ConvertIn(const Integer &a) const + {return (a<<(WORD_BITS*modulus.reg.size))%modulus;} + + Integer ConvertOut(const Integer &a) const; + + Integer One() const + {return Integer::Power2(WORD_BITS*modulus.reg.size)%modulus;} + + Integer Multiply(const Integer &a, const Integer &b) const; + + Integer Square(const Integer &a) const; + + Integer MultiplicativeInverse(const Integer &a) const; + + Integer Exponentiate(const Integer &a, const Integer &e) const + {return AbstractRing::Exponentiate(a, e);} + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const + {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} + +private: + Integer u; + SecWordBlock workspace; +}; + +// another alternative representation, e-mail me if you figure out how it works :) +class HalfMontgomeryRepresentation : public ModularArithmetic +{ +public: + HalfMontgomeryRepresentation(const Integer &modulus); // modulus must be odd + + Integer ConvertIn(const Integer &a) const + {return (a<<(WORD_BITS*modulus.reg.size/2))%modulus;} + + Integer ConvertOut(const Integer &a) const; + + Integer One() const + {return Integer::Power2(WORD_BITS*modulus.reg.size/2)%modulus;} + + Integer Multiply(const Integer &a, const Integer &b) const; + + Integer Square(const Integer &a) const; + + Integer MultiplicativeInverse(const Integer &a) const; + + Integer Exponentiate(const Integer &a, const Integer &e) const + {return AbstractRing::Exponentiate(a, e);} + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const + {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} + +private: + Integer v, u; + SecWordBlock workspace; +}; + +class GFP : public ModularArithmetic +{ +public: + GFP(const Integer &modulus) + : ModularArithmetic(modulus) {} + + bool IsUnit(const Integer &a) const + {return !!a;} + + Integer FieldSize() const + {return modulus;} +}; + +#endif diff --git a/src/cryptlib/nbtheory.cpp b/src/cryptlib/nbtheory.cpp new file mode 100644 index 0000000..a2a6d67 --- /dev/null +++ b/src/cryptlib/nbtheory.cpp @@ -0,0 +1,1030 @@ +// nbtheory.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "nbtheory.h" +#include "misc.h" +#include "asn.h" +#include "algebra.h" + +#include + +#include "algebra.cpp" +#include "eprecomp.cpp" + +USING_NAMESPACE(std) + +NAMESPACE_BEGIN(NumberTheory) + +const unsigned maxPrimeTableSize = 3511; +unsigned primeTableSize=552; + +word16 primeTable[maxPrimeTableSize] = + {2, 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003}; + +void BuildPrimeTable() +{ + unsigned int p=primeTable[primeTableSize-1]; + for (unsigned int i=primeTableSize; iprimeTable[primeTableSize-1]) + return false; + if (p==primeTable[primeTableSize-1]) + return true; + + for (unsigned i=0; primeTable[i]<=p; i++) + if (p == primeTable[i]) + return true; + + return false; +} + +bool TrialDivision(const Integer &p, unsigned bound) +{ + assert(primeTable[primeTableSize-1] >= bound); + + unsigned int i; + for (i = 0; primeTable[i]1 && b>Integer::Zero() && b1 && b>Integer::Zero() && b>a; + + Integer z = a_exp_b_mod_c(b, m, n); + if (z==1 || z==nminus1) + return true; + for (unsigned j=1; j1); + + if (n.IsEven()) + return n==2; + + Integer b=1, d; + unsigned int i=0; + int j; + + do + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + d = (b.Squared()-4)%n; + } + while ((j=Jacobi(d,n)) == 1); + + if (j==0) + return false; + else + return Lucas(n+1, b, n)==2; +} + +bool IsStrongLucasProbablePrime(const Integer &n) +{ + assert(n>1); + + if (n.IsEven()) + return n==2; + + Integer b=1, d; + unsigned int i=0; + int j; + + do + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + d = (b.Squared()-4)%n; + } + while ((j=Jacobi(d,n)) == 1); + + if (j==0) + return false; + + Integer n1 = n-j; + unsigned int a; + + // calculate a = largest power of 2 that divides n1 + for (a=0; ; a++) + if (n1.GetBit(a)) + break; + Integer m = n1>>a; + + Integer z = Lucas(m, b, n); + if (z==2 || z==n-2) + return true; + for (i=1; i table; +}; + +RemainderTable::RemainderTable(const Integer &p) + : table((BuildPrimeTable(), primeTableSize)) +{ + for (unsigned int i=0; i=primeTable[i]) + table[i]-=primeTable[i]; + } +} + +void RemainderTable::IncrementBy(const RemainderTable &rtQ) +{ + for (unsigned int i=0; i=primeTable[i]) + table[i]-=primeTable[i]; + } +} + +inline bool FastProbablePrimeTest(const Integer &n) +{ + return IsStrongProbablePrime(n,2); +} + +bool NextPrime(Integer &p, const Integer &max, bool blumInt) +{ + BuildPrimeTable(); + + if (pmax) + return false; + + RemainderTable rt(p); + + while (rt.HasZero() || !FastProbablePrimeTest(p) || !IsPrime(p)) + { + rt.IncrementBy(blumInt ? 4 : 2); + ++p; ++p; + if (blumInt) + {++p; ++p;} + + if (p>max) + return false; + } + + return true; +} + +Integer ProvablePrime(RandomNumberGenerator &rng, unsigned int bits) +{ + const unsigned smallPrimeBound = 29, c_opt=10; + Integer p; + + BuildPrimeTable(); + if (bits < smallPrimeBound) + { + do + p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ODD); + while (TrialDivision(p, 1 << ((bits+1)/2))); + } + else + { + const unsigned margin = bits > 50 ? 20 : (bits-10)/2; + double relativeSize; + do + relativeSize = pow(2.0, double(rng.GetLong())/0xffffffff - 1); + while (bits * relativeSize >= bits - margin); + + Integer a,b; + Integer q = ProvablePrime(rng, unsigned(bits*relativeSize)); + Integer I = Integer::Power2(bits-2)/q; + Integer I2 = I << 1; + unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt); + bool success = false; + do + { + p.Randomize(rng, I, I2, Integer::ANY); + p *= q; p <<= 1; ++p; + if (!TrialDivision(p, trialDivisorBound)) + { + a.Randomize(rng, 2, p-1, Integer::ANY); + b = a_exp_b_mod_c(a, (p-1)/q, p); + success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1); + } + } + while (!success); + } + return p; +} + +Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u) +{ + // isn't operator overloading great? + return p * (u * (xq-xp) % q) + xp; +} + +Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q) +{ + return CRT(xp, p, xq, q, EuclideanMultiplicativeInverse(p, q)); +} + +Integer ModularSquareRoot(const Integer &a, const Integer &p) +{ + if (p%4 == 3) + return a_exp_b_mod_c(a, (p+1)/4, p); + + Integer q=p-1; + unsigned int r=0; + while (q.IsEven()) + { + r++; + q >>= 1; + } + + Integer n=2; + while (Jacobi(n, p) != -1) + ++n; + + Integer y = a_exp_b_mod_c(n, q, p); + Integer x = a_exp_b_mod_c(a, (q-1)/2, p); + Integer b = (x.Squared()%p)*a%p; + x = a*x%p; + Integer tempb, t; + + while (b != 1) + { + unsigned m=0; + tempb = b; + do + { + m++; + b = b.Squared()%p; + if (m==r) + return Integer::Zero(); + } + while (b != 1); + + t = y; + for (unsigned i=0; i>= 1; + b >>= 1; + k++; + } + + while (a[0]==0) + a >>= 1; + + while (b[0]==0) + b >>= 1; + + while (1) + { + switch (a.Compare(b)) + { + case -1: + b -= a; + while (b[0]==0) + b >>= 1; + break; + + case 0: + return (a <<= k); + + case 1: + a -= b; + while (a[0]==0) + a >>= 1; + break; + + default: + assert(false); + } + } +} + +Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) +{ + assert(b.Positive()); + + if (a.Negative()) + return EuclideanMultiplicativeInverse(a%b, b); + + if (b[0]==0) + { + if (!b || a[0]==0) + return Integer::Zero(); // no inverse + if (a==1) + return 1; + Integer u = EuclideanMultiplicativeInverse(b, a); + if (!u) + return Integer::Zero(); // no inverse + else + return (b*(a-u)+1)/a; + } + + Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1; + + if (a[0]) + { + t1 = Integer::Zero(); + t3 = -b; + } + else + { + t1 = b2; + t3 = a>>1; + } + + while (!!t3) + { + while (t3[0]==0) + { + t3 >>= 1; + if (t1[0]==0) + t1 >>= 1; + else + { + t1 >>= 1; + t1 += b2; + } + } + if (t3.Positive()) + { + u = t1; + d = t3; + } + else + { + v1 = b-t1; + v3 = -t3; + } + t1 = u-v1; + t3 = d-v3; + if (t1.Negative()) + t1 += b; + } + if (d==1) + return u; + else + return Integer::Zero(); // no inverse +} +*/ + +int Jacobi(const Integer &aIn, const Integer &bIn) +{ + assert(bIn.IsOdd()); + + Integer b = bIn, a = aIn%bIn; + int result = 1; + + while (!!a) + { + unsigned i=0; + while (a.GetBit(i)==0) + i++; + a>>=i; + + if (i%2==1 && (b%8==3 || b%8==5)) + result = -result; + + if (a%4==3 && b%4==3) + result = -result; + + swap(a, b); + a %= b; + } + + return (b==1) ? result : 0; +} + +Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n) +{ + unsigned i = e.BitCount(); + if (i==0) + return 2; + + MontgomeryRepresentation m(n); + Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(2); + Integer v=p, v1=m.Subtract(m.Square(p), two); + + i--; + while (i--) + { + if (e.GetBit(i)) + { + // v = (v*v1 - p) % m; + v = m.Subtract(m.Multiply(v,v1), p); + // v1 = (v1*v1 - 2) % m; + v1 = m.Subtract(m.Square(v1), two); + } + else + { + // v1 = (v*v1 - p) % m; + v1 = m.Subtract(m.Multiply(v,v1), p); + // v = (v*v - 2) % m; + v = m.Subtract(m.Square(v), two); + } + } + return m.ConvertOut(v); +} + +// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm. +// The total number of multiplies and squares used is less than the binary +// algorithm (see above). Unfortunately I can't get it to run as fast as +// the binary algorithm because of the extra overhead. +/* +Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus) +{ + if (!n) + return 2; + +#define f(A, B, C) m.Subtract(m.Multiply(A, B), C) +#define X2(A) m.Subtract(m.Square(A), two) +#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three)) + + MontgomeryRepresentation m(modulus); + Integer two=m.ConvertIn(2), three=m.ConvertIn(3); + Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U; + + while (d!=1) + { + p = d; + unsigned int b = WORD_BITS * p.WordCount(); + Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1); + r = (p*alpha)>>b; + e = d-r; + B = A; + C = two; + d = r; + + while (d!=e) + { + if (d>2)) + if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t)) + { + // #1 +// t = (d+d-e)/3; +// t = d; t += d; t -= e; t /= 3; +// e = (e+e-d)/3; +// e += e; e -= d; e /= 3; +// d = t; + +// t = (d+e)/3 + t = d; t += e; t /= 3; + e -= t; + d -= t; + + T = f(A, B, C); + U = f(T, A, B); + B = f(T, B, A); + A = U; + continue; + } + +// if (dm6 == em6 && d <= e + (e>>2)) + if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t)) + { + // #2 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + +// if (d <= (e<<2)) + if (d <= (t = e, t <<= 2)) + { + // #3 + d -= e; + C = f(A, B, C); + swap(B, C); + continue; + } + + if (dm2 == em2) + { + // #4 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + + if (dm2 == 0) + { + // #5 + d >>= 1; + C = f(A, C, B); + A = X2(A); + continue; + } + + if (dm3 == 0) + { + // #6 +// d = d/3 - e; + d /= 3; d -= e; + T = X2(A); + C = f(T, f(A, B, C), C); + swap(B, C); + A = f(T, A, A); + continue; + } + + if (dm3+em3==0 || dm3+em3==3) + { + // #7 +// d = (d-e-e)/3; + d -= e; d -= e; d /= 3; + T = f(A, B, C); + B = f(T, A, B); + A = X3(A); + continue; + } + + if (dm3 == em3) + { + // #8 +// d = (d-e)/3; + d -= e; d /= 3; + T = f(A, B, C); + C = f(A, C, B); + B = T; + A = X3(A); + continue; + } + + assert(em2 == 0); + // #9 + e >>= 1; + C = f(C, B, A); + B = X2(B); + } + + A = f(A, B, C); + } + +#undef f +#undef X2 +#undef X3 + + return m.ConvertOut(A); +} +*/ + +Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) +{ + Integer d = (m*m-4); + Integer p2 = p-Jacobi(d,p); + Integer q2 = q-Jacobi(d,q); + return CRT(Lucas(EuclideanMultiplicativeInverse(e,p2), m, p), p, Lucas(EuclideanMultiplicativeInverse(e,q2), m, q), q, u); +} + +Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q) +{ + return InverseLucas(e, m, p, q, EuclideanMultiplicativeInverse(p, q)); +} + +unsigned int FactoringWorkFactor(unsigned int n) +{ + // extrapolated from the table in Odlyzko's "The Future of Integer Factorization" + // updated to reflect the factoring of RSA-130 + if (n<5) return 0; + else return (unsigned int)(2.4 * pow(n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); +} + +unsigned int DiscreteLogWorkFactor(unsigned int n) +{ + // assuming discrete log takes about the same time as factoring + if (n<5) return 0; + else return (unsigned int)(2.4 * pow(n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); +} + +NAMESPACE_END + +// ******************************************************** + +USING_NAMESPACE(NumberTheory) + +// generate a random prime p of the form 2*q+delta, where q is also prime +// warning: this is slow! +PrimeAndGenerator::PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits) +{ + Integer minQ = Integer::Power2(pbits-2); + Integer maxQ = Integer::Power2(pbits-1) - 1; + + do + { + q.Randomize(rng, minQ, maxQ, Integer::ODD); + p = 2*q+delta; + + RemainderTable rtQ(q); + RemainderTable rtP(p); + + while (rtQ.HasZero() || rtP.HasZero() || + !FastProbablePrimeTest(q) || !FastProbablePrimeTest(p) || + !IsPrime(q) || !IsPrime(p)) + { + rtQ.IncrementBy(2); + rtP.IncrementBy(4); + ++q; ++q; + ++p; ++p; ++p; ++p; + } + } while (q>maxQ); + + if (delta == 1) + { + // find g such that g is a quadratic residue mod p, then g has order q + // g=4 always works, but this way we get the smallest quadratic residue (other than 1) + for (g=2; Jacobi(g, p) != 1; ++g); + } + else + { + assert(delta == -1); + // find g such that g*g-4 is a quadratic non-residue, + // and such that g has order q + for (g=3; ; ++g) + if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) + break; + } +} + +// generate a random prime p of the form 2*r*q+delta, where q is also prime +PrimeAndGenerator::PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) +{ + assert(pbits > qbits); + + Integer minQ = Integer::Power2(qbits-1); + Integer maxQ = Integer::Power2(qbits) - 1; + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + + while (1) + { + q.Randomize(rng, minQ, maxQ, Integer::PRIME); + Integer q2 = 2*q; + RemainderTable rtq2(q2); + + // generate a random number of the form 2*r*q+delta + p.Randomize(rng, minP, maxP, Integer::ANY); + p = p - p%q2 + q2 + delta; + RemainderTable rtp(p); + + // now increment p by 2*q until p is prime + while (p<=maxP) + { + if (rtp.HasZero() || !FastProbablePrimeTest(p) || !IsPrime(p)) + { + p += q2; + rtp.IncrementBy(rtq2); + } + else + { + // find a random g of order q + if (delta==1) + { + do + { + Integer h(rng, 2, p-2, Integer::ANY); + g = a_exp_b_mod_c(h, (p-1)/q, p); + } while (g <= 1); + assert(a_exp_b_mod_c(g, q, p)==1); + } + else + { + assert(delta==-1); + do + { + Integer h(rng, 3, p-2, Integer::ANY); + if (Jacobi(h*h-4, p)==1) + continue; + g = Lucas((p+1)/q, h, p); + } while (g <= 2); + assert(Lucas(q, g, p) == 2); + } + return; + } + } + } +} + +// ******************************************************** + +ModExpPrecomputation::~ModExpPrecomputation() {} + +ModExpPrecomputation::ModExpPrecomputation(const Integer &modulus, const Integer &base, unsigned int maxExpBits, unsigned int storage) +{ + Precompute(modulus, base, maxExpBits, storage); +} + +ModExpPrecomputation::ModExpPrecomputation(const ModExpPrecomputation &mep) + : mr(new MontgomeryRepresentation(*mep.mr)), + mg(new MR_MG(*mr)), + ep(new ExponentiationPrecomputation(*mg, *mep.ep)) +{ +} + +void ModExpPrecomputation::Precompute(const Integer &modulus, const Integer &base, unsigned int maxExpBits, unsigned int storage) +{ + if (!mr.get() || mr->GetModulus()!=modulus) + { + mr.reset(new MontgomeryRepresentation(modulus)); + mg.reset(new MR_MG(*mr)); + ep.reset(NULL); + } + + if (!ep.get() || ep->storage < storage) + ep.reset(new ExponentiationPrecomputation(*mg, mr->ConvertIn(base), maxExpBits, storage)); +} + +void ModExpPrecomputation::Load(const Integer &modulus, BufferedTransformation &bt) +{ + if (!mr.get() || mr->GetModulus()!=modulus) + { + mr.reset(new MontgomeryRepresentation(modulus)); + mg.reset(new MR_MG(*mr)); + } + + ep.reset(new ExponentiationPrecomputation(*mg)); + BERSequenceDecoder seq(bt); + ep->storage = (unsigned int)(Integer(seq).ConvertToLong()); + ep->exponentBase.BERDecode(seq); + ep->g.resize(ep->storage); + for (unsigned i=0; istorage; i++) + ep->g[i].BERDecode(seq); +} + +void ModExpPrecomputation::Save(BufferedTransformation &bt) const +{ + assert(ep.get() != 0); + DERSequenceEncoder seq(bt); + Integer(ep->storage).DEREncode(seq); + ep->exponentBase.DEREncode(seq); + for (unsigned i=0; istorage; i++) + ep->g[i].DEREncode(seq); +} + +Integer ModExpPrecomputation::Exponentiate(const Integer &exponent) const +{ + assert(mr.get() && ep.get()); + return mr->ConvertOut(ep->Exponentiate(exponent)); +} + +Integer ModExpPrecomputation::CascadeExponentiate(const Integer &exponent, + ModExpPrecomputation pc2, const Integer &exponent2) const +{ + assert(mr.get() && ep.get()); + return mr->ConvertOut(ep->CascadeExponentiate(exponent, *pc2.ep, exponent2)); +} diff --git a/src/cryptlib/nbtheory.h b/src/cryptlib/nbtheory.h new file mode 100644 index 0000000..8c324b9 --- /dev/null +++ b/src/cryptlib/nbtheory.h @@ -0,0 +1,141 @@ +// nbtheory.h - written and placed in the public domain by Wei Dai + +#ifndef NBTHEORY_H +#define NBTHEORY_H + +#include "modarith.h" +#include "eprecomp.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(NumberTheory) + // export a table of small primes + extern const unsigned maxPrimeTableSize; + extern unsigned primeTableSize; + extern word16 primeTable[]; + + // build up the table to maxPrimeTableSize + void BuildPrimeTable(); + + // ************ primality testing **************** + + // generate a provable prime + Integer ProvablePrime(RandomNumberGenerator &rng, unsigned int bits); + + bool IsSmallPrime(const Integer &p); + + // returns true if p is divisible by some prime less than bound + // bound not be greater than the largest entry in the prime table + bool TrialDivision(const Integer &p, unsigned bound); + + // returns true if p is NOT divisible by small primes + bool SmallDivisorsTest(const Integer &p); + + // These is no reason to use these two, use the ones below instead + bool IsFermatProbablePrime(const Integer &n, const Integer &b); + bool IsLucasProbablePrime(const Integer &n); + + bool IsStrongProbablePrime(const Integer &n, const Integer &b); + bool IsStrongLucasProbablePrime(const Integer &n); + + // Rabin-Miller primality test, i.e. repeating the strong probable prime test + // for several rounds with random bases + bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds); + + // small divisors test + strong probable prime test + strong Lucas probable prime test + // should be good enough for all practical purposes + // but feel free to change this to suit your level of paranoia + bool IsPrime(const Integer &p); + + // use a fast sieve to find the next probable prime after p + // returns true iff successful + bool NextPrime(Integer &p, const Integer &max, bool blumInt=false); + + // ********** other number theoretic functions ************ + + inline Integer GCD(const Integer &a, const Integer &b) + {return Integer::Gcd(a,b);} + inline Integer LCM(const Integer &a, const Integer &b) + {return a/GCD(a,b)*b;} + inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) + {return a.InverseMod(b);} + + // use Chinese Remainder Theorem to calculate x given x mod p and x mod q + Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q); + // use this one if u = inverse of p mod q has been precalculated + Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u); + + // if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise + // check a number theory book for what Jacobi symbol means when b is not prime + int Jacobi(const Integer &a, const Integer &b); + + // calculates the Lucas function V_e(p, 1) mod n + Integer Lucas(const Integer &e, const Integer &p, const Integer &n); + // calculates x such that m==Lucas(e, x, p*q), p q primes + Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q); + // use this one if u=inverse of p mod q has been precalculated + Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u); + + inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m) + {return a_exp_b_mod_c(a, e, m);} + // returns x such that x*x%p == a, p prime + Integer ModularSquareRoot(const Integer &a, const Integer &p); + // returns x such that a==ModularExponentiation(x, e, p*q), p q primes, + // and e relatively prime to (p-1)*(q-1) + Integer ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q); + // use this one if dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1)) + // and u=inverse of p mod q have been precalculated + Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u); + + // returns log base 2 of estimated number of operations to calculate discrete log or factor a number + unsigned int DiscreteLogWorkFactor(unsigned int bitlength); + unsigned int FactoringWorkFactor(unsigned int bitlength); +NAMESPACE_END + +USING_NAMESPACE(NumberTheory) + +// ******************************************************** + +class PrimeAndGenerator +{ +public: + // generate a random prime p of the form 2*q+delta, where q is also prime + // warning: this is slow! + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits); + // generate a random prime p of the form 2*r*q+delta, where q is also prime + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits); + + const Integer& Prime() const {return p;} + const Integer& SubPrime() const {return q;} + const Integer& Generator() const {return g;} + +private: + Integer p, q, g; +}; + +// ******************************************************** + +class ModExpPrecomputation +{ +public: + ModExpPrecomputation() {} + ModExpPrecomputation(const ModExpPrecomputation &mep); + ModExpPrecomputation(const Integer &modulus, const Integer &base, unsigned int maxExpBits, unsigned int storage); + ~ModExpPrecomputation(); + + void operator=(const ModExpPrecomputation &); + + void Precompute(const Integer &modulus, const Integer &base, unsigned int maxExpBits, unsigned int storage); + void Load(const Integer &modulus, BufferedTransformation &storedPrecomputation); + void Save(BufferedTransformation &storedPrecomputation) const; + + Integer Exponentiate(const Integer &exponent) const; + Integer CascadeExponentiate(const Integer &exponent, ModExpPrecomputation pc2, const Integer &exponent2) const; + +private: + typedef MultiplicativeGroup MR_MG; + member_ptr mr; + member_ptr mg; + member_ptr< ExponentiationPrecomputation > ep; +}; + +#endif diff --git a/src/cryptlib/pch.cpp b/src/cryptlib/pch.cpp new file mode 100644 index 0000000..1d9f38c --- /dev/null +++ b/src/cryptlib/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/cryptlib/pch.h b/src/cryptlib/pch.h new file mode 100644 index 0000000..480903a --- /dev/null +++ b/src/cryptlib/pch.h @@ -0,0 +1,18 @@ +#ifndef PCH_H +#define PCH_H + +#include "config.h" + +#ifdef USE_PRECOMPILED_HEADERS +#include "cryptlib.h" +#include "misc.h" +#include "smartptr.h" +/* +#include +#include +#include +#include +*/ +#endif + +#endif diff --git a/src/cryptlib/queue.cpp b/src/cryptlib/queue.cpp new file mode 100644 index 0000000..6501128 --- /dev/null +++ b/src/cryptlib/queue.cpp @@ -0,0 +1,266 @@ +// queue.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "queue.h" +#include "misc.h" + +// this class for use by ByteQueue only +class ByteQueueNode +{ +public: + ByteQueueNode(unsigned int maxSize); + + unsigned int CurrentSize() const + {return tail-head;} + unsigned int UsedUp() const + {return (head==MaxSize());} + + unsigned int Put(byte inByte); + unsigned int Put(const byte *inString, unsigned int length); + + unsigned int Get(byte &outByte); + unsigned int Get(byte *outString, unsigned int getMax); + + unsigned int Peek(byte &outByte) const; + + void CopyTo(BufferedTransformation &target) const + {target.Put(buf+head, tail-head);} + void CopyTo(byte *target) const + {memcpy(target, buf+head, tail-head);} + + byte operator[](unsigned int i) const + {return buf[i-head];} + + ByteQueueNode *next; + +private: + unsigned int MaxSize() const {return buf.size;} + + SecByteBlock buf; + unsigned int head, tail; +}; + + +ByteQueueNode::ByteQueueNode(unsigned int maxSize) + : buf(maxSize) +{ + head = tail = 0; + next = 0; +} + +unsigned int ByteQueueNode::Put(byte inByte) +{ + if (MaxSize()==tail) + return 0; + + buf[tail++]=inByte; + return 1; +} + +unsigned int ByteQueueNode::Put(const byte *inString, unsigned int length) +{ + unsigned int l = STDMIN(length, MaxSize()-tail); + memcpy(buf+tail, inString, l); + tail += l; + return l; +} + +unsigned int ByteQueueNode::Get(byte &outByte) +{ + if (tail==head) + return 0; + + outByte=buf[head++]; + return 1; +} + +unsigned int ByteQueueNode::Get(byte *outString, unsigned int getMax) +{ + unsigned int l = STDMIN(getMax, tail-head); + memcpy(outString, buf+head, l); + head += l; + return l; +} + +unsigned int ByteQueueNode::Peek(byte &outByte) const +{ + if (tail==head) + return 0; + + outByte=buf[head]; + return 1; +} + +// ******************************************************** + +ByteQueue::ByteQueue(unsigned int nodeSize) + : nodeSize(nodeSize) +{ + head = tail = new ByteQueueNode(nodeSize); +} + +ByteQueue::ByteQueue(const ByteQueue ©) +{ + CopyFrom(copy); +} + +void ByteQueue::CopyFrom(const ByteQueue ©) +{ + nodeSize = copy.nodeSize; + head = tail = new ByteQueueNode(*copy.head); + + for (ByteQueueNode *current=copy.head->next; current; current=current->next) + { + tail->next = new ByteQueueNode(*current); + tail = tail->next; + } + + tail->next = NULL; +} + +ByteQueue::~ByteQueue() +{ + Destroy(); +} + +void ByteQueue::Destroy() +{ + ByteQueueNode *next; + + for (ByteQueueNode *current=head; current; current=next) + { + next=current->next; + delete current; + } +} + +void ByteQueue::CopyTo(BufferedTransformation &target) const +{ + for (ByteQueueNode *current=head; current; current=current->next) + current->CopyTo(target); +} + +void ByteQueue::CopyTo(byte *target) const +{ + for (ByteQueueNode *current=head; current; current=current->next) + { + current->CopyTo(target); + target += current->CurrentSize(); + } +} + +unsigned long ByteQueue::CurrentSize() const +{ + unsigned long size=0; + + for (ByteQueueNode *current=head; current; current=current->next) + size += current->CurrentSize(); + + return size; +} + +void ByteQueue::Put(byte inByte) +{ + if (!tail->Put(inByte)) + { + tail->next = new ByteQueueNode(nodeSize); + tail = tail->next; + tail->Put(inByte); + } +} + +void ByteQueue::Put(const byte *inString, unsigned int length) +{ + unsigned int l; + + while ((l=tail->Put(inString, length)) < length) + { + tail->next = new ByteQueueNode(nodeSize); + tail = tail->next; + inString += l; + length -= l; + } +} + +unsigned int ByteQueue::Get(byte &outByte) +{ + int l = head->Get(outByte); + if (head->UsedUp()) + { + ByteQueueNode *temp=head; + head = head->next; + delete temp; + if (!head) // just deleted the last node + head = tail = new ByteQueueNode(nodeSize); + } + return l; +} + +unsigned int ByteQueue::Get(byte *outString, unsigned int getMax) +{ + unsigned int getMaxSave=getMax; + ByteQueueNode *current=head; + + while (getMax && current) + { + int l=current->Get(outString, getMax); + + outString += l; + getMax -= l; + + current = current->next; + } + + while (head && head->UsedUp()) + { + current=head; + head=head->next; + delete current; + } + + if (!head) // every single node has been used up and deleted + head = tail = new ByteQueueNode(nodeSize); + + return (getMaxSave-getMax); +} + +unsigned int ByteQueue::Peek(byte &outByte) const +{ + return head->Peek(outByte); +} + +ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) +{ + Destroy(); + CopyFrom(rhs); + return *this; +} + +bool ByteQueue::operator==(const ByteQueue &rhs) const +{ + const unsigned long currentSize = CurrentSize(); + + if (currentSize != rhs.CurrentSize()) + return false; + + for (unsigned long i = 0; inext) + { + if (i < current->CurrentSize()) + return (*current)[i]; + + i -= current->CurrentSize(); + } + + // i should be less than CurrentSize(), therefore we should not be here + assert(false); + return 0; +} diff --git a/src/cryptlib/queue.h b/src/cryptlib/queue.h new file mode 100644 index 0000000..62e07bf --- /dev/null +++ b/src/cryptlib/queue.h @@ -0,0 +1,48 @@ +// specification file for an unlimited queue for storing bytes + +#ifndef QUEUE_H +#define QUEUE_H + +#include "cryptlib.h" + +// The queue is implemented as a linked list of arrays, but you don't need to +// know about that. So just ignore this next line. :) +class ByteQueueNode; + +class ByteQueue : public BufferedTransformation +{ +public: + ByteQueue(unsigned int nodeSize=256); + ByteQueue(const ByteQueue ©); + ~ByteQueue(); + + // how many bytes currently stored + unsigned long CurrentSize() const; + unsigned long MaxRetrieveable() + {return CurrentSize();} + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + + // both functions returns the number of bytes actually retrived + unsigned int Get(byte &outByte); + unsigned int Get(byte *outString, unsigned int getMax); + + unsigned int Peek(byte &outByte) const; + + void CopyTo(BufferedTransformation &target) const; + void CopyTo(byte *target) const; + + ByteQueue & operator=(const ByteQueue &rhs); + bool operator==(const ByteQueue &rhs) const; + byte operator[](unsigned long i) const; + +private: + void CopyFrom(const ByteQueue ©); + void Destroy(); + + unsigned int nodeSize; + ByteQueueNode *head, *tail; +}; + +#endif diff --git a/src/cryptlib/readme.txt b/src/cryptlib/readme.txt new file mode 100644 index 0000000..29e0548 --- /dev/null +++ b/src/cryptlib/readme.txt @@ -0,0 +1,94 @@ +Crypto++: a C++ Class Library of Cryptographic Primitives +Version 2.3 1/17/1998 + +This library includes: + +MD5, SHA, HAVAL, Tiger, RIPE-MD160, MD5-MAC, HMAC, XOR-MAC, DES, IDEA, +WAKE, 3-WAY, TEA, SAFER, Blowfish, SHARK, GOST, CAST-128, Square, Diamond2, +Sapphire, RC5, SEAL, Luby-Rackoff, MDC, various encryption modes (CFB, +CBC, OFB, counter), DH, DSA, ElGamal, LUC, LUCDIF, LUCELG, Rabin, RSA, +BlumGoldwasser, elliptic curve cryptosystems, BBS, DEFLATE compression, +Shamir's secret sharing scheme, Rabin's information dispersal scheme. +There are also various miscellanous modules such as base 64 coding and +32-bit CRC. + +You are welcome to use it for any purpose without paying me, but see +license.txt for the fine print. + +Crypto++ has been compiled successfully with MSVC 5.0 and EGCS/cygwin32 +1.0 on Windows NT 4.0. + +To compile Crypto++ with MSVC, open the "cryptest.dsw" workspace file +and build the "cryptest" project. This will compile Crypto++ as a static +library and also build the test driver. Run the test driver and make sure +the validation suite passes. Then to use the library simply insert the +"cryptlib.dsp" project file into your own application workspace as a +dependent project. + +A makefile is included for you to compile Crypto++ with EGCS. But first +you may have to make some changes to the system header files to work around +problems in the EGCS 1.0 release. Please check the Crypto++ homepage +(see below) for the latest updates. + +Right now there is very little documentation for Crypto++. If you are +not familiar with cryptography, I suggest that you read an introductory +text (such as Bruce Schneier's _Applied Cryptography_) before attempting +to use this library. Otherwise, you should start by looking at +cryptlib.h, which contains the main abstract base classes and their +descriptions, and test.cpp, which contains sample/test code. + +Finally, a note on object ownership: If a constructor for A takes +a pointer to an object B (except primitive types such as int and char), +then A owns B and will delete B at A's destruction. If a constructor +for A takes a reference to an object B, then the caller retains ownership +of B and should not destroy it until A no longer needs it. + +Good luck, and feel free to e-mail me at weidai@eskimo.com if you have +any problems. Also, check http://www.eskimo.com/~weidai/cryptlib.html +for updates and new versions. + +Wei Dai + +History + +1.0 - First public release. Withdrawn at the request of RSA DSI. + - included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA, + MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression + - had a big bug in the RSA key generation code. + +1.1 - Removed RSA, RC4, RC5 + - Disabled calls to RSAREF's non-public functions + - Minor bugs fixed + +2.0 - a completely new, faster multiprecision integer class + - added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser, + elliptic curve algorithms + - added the Lucas strong probable primality test + - ElGamal encryption and signature schemes modified to avoid weaknesses + - Diamond changed to Diamond2 because of key schedule weakness + - fixed bug in WAKE key setup + - SHS class renamed to SHA + - lots of miscellaneous optimizations + +2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC, + OAEP, PSSR, SHARK + - added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms + - added back RC5 and a new RSA + - optimizations in elliptic curves over GF(p) + - changed Rabin to use OAEP and PSSR + - changed many classes to allow copy constructors to work correctly + - improved exception generation and handling + +2.2 - added SEAL, CAST-128, Square + - fixed bug in HAVAL (padding problem) + - fixed bug in triple-DES (decryption order was reversed) + - fixed bug in RC5 (couldn't handle key length not a multiple of 4) + - changed HMAC to conform to RFC-2104 (which is not compatible + with the original HMAC) + - changed secret sharing and information dispersal to use GF(2^32) + instead of GF(65521) + - removed zero knowledge prover/verifier for graph isomorphism + - removed several utility classes in favor of the C++ standard library + +2.3 - ported to EGCS + - fixed incomplete workaround of min/max conflict in MSVC diff --git a/src/cryptlib/rmcr.pl b/src/cryptlib/rmcr.pl new file mode 100755 index 0000000..d15f728 --- /dev/null +++ b/src/cryptlib/rmcr.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl -w + +# rmcr.pl +# +# remove all "\r\n" sequences. + +if (!$ARGV[0]) { + print <)) + { + $instring =~ s/\r\n/\n/; + $buffer .= $instring; + } + close (IN); + + if (open (OUT, ">$filename")) + { + print OUT $buffer; + close (OUT); + } + else + { + print "Could not open $filename for writing.\n"; + } + } + else + { + print "Could not open $filename for reading.\n"; + } +} diff --git a/src/cryptlib/rng.cpp b/src/cryptlib/rng.cpp new file mode 100644 index 0000000..013a708 --- /dev/null +++ b/src/cryptlib/rng.cpp @@ -0,0 +1,120 @@ +// rng.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rng.h" + +#include +#include + +// linear congruential generator +// originally by William S. England + +// do not use for cryptographic purposes + +/* +** Original_numbers are the original published m and q in the +** ACM article above. John Burton has furnished numbers for +** a reportedly better generator. The new numbers are now +** used in this program by default. +*/ + +#ifndef LCRNG_ORIGINAL_NUMBERS +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=44488L; + +const word16 LC_RNG::a=(unsigned int)48271L; +const word16 LC_RNG::r=3399; +#else +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=127773L; + +const word16 LC_RNG::a=16807; +const word16 LC_RNG::r=2836; +#endif + +byte LC_RNG::GetByte() +{ + word32 hi = seed/q; + word32 lo = seed%q; + + long test = a*lo - r*hi; + + if (test > 0) + seed = test; + else + seed = test+ m; + + return (seedBytes[0] ^ seedBytes[1] ^ seedBytes[2] ^ seedBytes[3]); +} + +// ******************************************************** + +X917RNG::X917RNG(BlockTransformation *c, const byte *seed) + : cipher(c), + S(cipher->BlockSize()), + dtbuf(S), + randseed(seed, S), + randbuf(S), + randbuf_counter(0) +{ + time_t tstamp1 = time(0); + xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S)); + cipher->ProcessBlock(dtbuf); + clock_t tstamp2 = clock(); + xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S)); + cipher->ProcessBlock(dtbuf); +} + +byte X917RNG::GetByte() +{ + if (randbuf_counter==0) + { + // calculate new enciphered timestamp + clock_t tstamp = clock(); + xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S)); + cipher->ProcessBlock(dtbuf); + + // combine enciphered timestamp with seed + xorbuf(randseed, dtbuf, S); + + // generate a new block of random bytes + cipher->ProcessBlock(randseed, randbuf); + + // compute new seed vector + for (unsigned int i=0; i<(unsigned int)S; i++) + randseed[i] = randbuf[i] ^ dtbuf[i]; + cipher->ProcessBlock(randseed); + + randbuf_counter=S; + } + return(randbuf[(unsigned int)--randbuf_counter]); +} + +MaurerRandomnessTest::MaurerRandomnessTest() + : sum(0.0), n(0) +{ + for (unsigned i=0; i= Q) + sum += log(double(n - tab[inByte])); + tab[inByte] = n; + n++; +} + +void MaurerRandomnessTest::Put(const byte *inString, unsigned int length) +{ + while (length--) + Put(*inString++); +} + +double MaurerRandomnessTest::GetTestValue() const +{ + double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer + + double value = fTu * 0.1392; // arbitrarily normalize it to + return value > 1.0 ? 1.0 : value; // a number between 0 and 1 +} diff --git a/src/cryptlib/rng.h b/src/cryptlib/rng.h new file mode 100644 index 0000000..7d4a254 --- /dev/null +++ b/src/cryptlib/rng.h @@ -0,0 +1,77 @@ +#ifndef RNG_H +#define RNG_H + +#include "cryptlib.h" +#include "filters.h" + +// linear congruential generator +// originally by William S. England + +// do not use for cryptographic purposes + +class LC_RNG : public RandomNumberGenerator +{ +public: + LC_RNG(word32 init_seed) + : seedBytes((byte *)&seed) {seed=init_seed;} + + byte GetByte(); + + word32 GetSeed() {return seed;} + +private: + word32 seed; + byte *const seedBytes; + + static const word32 m; + static const word32 q; + static const word16 a; + static const word16 r; +}; + +// RNG derived from ANSI X9.17 Appendix C + +class X917RNG : public RandomNumberGenerator +{ +public: + // cipher will be deleted by destructor + X917RNG(BlockTransformation *cipher, const byte *seed); + + byte GetByte(); + +private: + member_ptr cipher; + const int S; // blocksize of cipher + SecByteBlock dtbuf; // buffer for enciphered timestamp + SecByteBlock randseed, randbuf; + int randbuf_counter; // # of unused bytes left in randbuf +}; + +// This class implements Maurer's Universal Statistical Test for Random Bit Generators +// it is intended for measuring the randomness of *PHYSICAL* RNGs. +// For more details see his paper in Journal of Cryptology, 1992. + +class MaurerRandomnessTest : public Sink +{ +public: + MaurerRandomnessTest(); + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + + // BytesNeeded() returns how many more bytes of input is needed by the test + // GetTestValue() should not be called before BytesNeeded()==0 + unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;} + + // returns a number between 0.0 and 1.0, describing the quality of the + // random numbers entered + double GetTestValue() const; + +private: + enum {L=8, V=256, Q=2000, K=2000}; + double sum; + unsigned int n; + unsigned int tab[V]; +}; + +#endif diff --git a/src/cryptlib/sha.cpp b/src/cryptlib/sha.cpp new file mode 100644 index 0000000..1772a2a --- /dev/null +++ b/src/cryptlib/sha.cpp @@ -0,0 +1,217 @@ +// sha.cpp - modified by Wei Dai from Peter Gutmann's code +// Copyright 1992 by Peter Gutmann. Distributed with permission. + +#include "pch.h" +#include "sha.h" + +SHA::SHA() + : IteratedHash(DATASIZE, DIGESTSIZE) +{ + Init(); +} + +void SHA::Init() +{ + countLo = countHi = 0; + + digest[(unsigned int)0] = 0x67452301L; + digest[(unsigned int)1] = 0xEFCDAB89L; + digest[(unsigned int)2] = 0x98BADCFEL; + digest[(unsigned int)3] = 0x10325476L; + digest[(unsigned int)4] = 0xC3D2E1F0L; +} + +void SHA::HashBlock(const word32 *input) +{ +#ifndef WORDS_BIGENDIAN + byteReverse(data.ptr, input, (unsigned int)DATASIZE); + Transform(digest, data); +#else + Transform(digest, input); +#endif +} + +void SHA::Final(byte *hash) +{ + PadLastBlock(56); + CorrectEndianess(data, data, 56); + + data[(unsigned int)14] = countHi; + data[(unsigned int)15] = countLo; + + Transform(digest, data); + CorrectEndianess(digest, digest, DIGESTSIZE); + memcpy(hash, digest, DIGESTSIZE); + + Init(); // reinit for next use +} + + +/* The SHA f()-functions. The f1 and f3 functions can be optimized to + save one bool operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ +#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +/*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ +#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHA Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ + +/* The initial expanding function. The hash function is defined over an + 80-word expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHA changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#ifdef NEW_SHA + #define expand(W,i) ( W[ i & 15 ] = rotl( (W[i&15] ^ W[i-14&15] ^ \ + W[i-8&15] ^ W[i-3&15]), 1U) ) +#else + #define expand(W,i) ( W[ i & 15 ] ^= W[ i - 14 & 15 ] ^ W[ i - 8 & 15 ] ^ W[ i - 3 & 15 ] ) +#endif /* NEW_SHA */ + +/* The prototype SHA sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += rotl(a,5U) + f(b,c,d) + k + data, b = rotl(b,30U)) + +/* Perform the SHA transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds */ + +void SHA::Transform( word32 *digest, const word32 *data ) +{ + word32 eData[16]; + memcpy( eData, data, DATASIZE ); + + register word32 A, B, C, D, E; + A = digest[0]; + B = digest[1]; + C = digest[2]; + D = digest[3]; + E = digest[4]; + + // Heavy mangling, in 4 sub-rounds of 20 interations each. + subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); + subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); + subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); + subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); + subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); + + subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); + + subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); + + subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); + + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; + + memset(eData, 0, DATASIZE); +} diff --git a/src/cryptlib/sha.h b/src/cryptlib/sha.h new file mode 100644 index 0000000..f33c9a3 --- /dev/null +++ b/src/cryptlib/sha.h @@ -0,0 +1,32 @@ +#ifndef SHA_H +#define SHA_H + +#include "iterhash.h" + +class SHA : public IteratedHash +{ +public: + SHA(); + void Final(byte *hash); + unsigned int DigestSize() const {return DIGESTSIZE;}; + + static void CorrectEndianess(word32 *out, const word32 *in, unsigned int byteCount) + { +#ifdef WORDS_BIGENDIAN + if (in!=out) + memcpy(out, in, byteCount); +#else + byteReverse(out, in, byteCount); +#endif + } + + static void Transform(word32 *digest, const word32 *data ); + + enum {DIGESTSIZE = 20, DATASIZE = 64}; + +private: + void Init(); + void HashBlock(const word32 *input); +}; + +#endif diff --git a/src/cryptlib/smartptr.h b/src/cryptlib/smartptr.h new file mode 100644 index 0000000..ae619e3 --- /dev/null +++ b/src/cryptlib/smartptr.h @@ -0,0 +1,130 @@ +#ifndef SMARTPTR_H +#define SMARTPTR_H + +#include + +template class member_ptr +{ +public: + explicit member_ptr(T *p = 0) : m_p(p) {} + + ~member_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return m_p; } + + const T* get() const { return m_p; } + T* get() { return m_p; } + + T* release() + { + T *old_p = m_p; + m_p = 0; + return old_p; + } + + void reset(T *p = 0); + +private: + member_ptr(const member_ptr& rhs); // copy not allowed + void operator=(const member_ptr& rhs); // assignment not allowed + + T *m_p; +}; + +template member_ptr::~member_ptr() {delete m_p;} +template void member_ptr::reset(T *p) {delete m_p; m_p = p;} + +// ******************************************************** + +template class counted_ptr +{ +public: + explicit counted_ptr(T *p = 0); + counted_ptr(const counted_ptr& rhs); + + ~counted_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return m_p; } + + const T* get() const { return m_p; } + T* get() { return m_p; } + + counted_ptr & operator=(const counted_ptr& rhs); + +private: + T *m_p; +}; + +template counted_ptr::counted_ptr(T *p) + : m_p(p) +{ + if (m_p) + m_p->m_referenceCount = 1; +} + +template counted_ptr::counted_ptr(const counted_ptr& rhs) + : m_p(rhs.m_p) +{ + if (m_p) + m_p->m_referenceCount++; +} + +template counted_ptr::~counted_ptr() +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; +} + +template counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; + m_p = rhs.m_p; + if (m_p) + m_p->m_referenceCount++; + return *this; +} + +// ******************************************************** + +template class vector_member_ptrs +{ +public: + vector_member_ptrs(unsigned int size=0) + : _size(size) {ptr = new member_ptr[_size];} + ~vector_member_ptrs() + {delete [] ptr;} + + member_ptr& operator[](unsigned int index) + {assert(index<_size); return ptr[index];} + const member_ptr& operator[](unsigned int index) const + {assert(index<_size); return ptr[index];} + + unsigned int size() const {return _size;} + void resize(unsigned int newSize) + { + member_ptr *newPtr = new member_ptr[newSize]; + for (unsigned int i=0; i &c); // copy not allowed + void operator=(const vector_member_ptrs &x); // assignment not allowed + + unsigned int _size; + member_ptr *ptr; +}; + +#endif diff --git a/src/cryptlib/words.h b/src/cryptlib/words.h new file mode 100644 index 0000000..a5a6d22 --- /dev/null +++ b/src/cryptlib/words.h @@ -0,0 +1,97 @@ +#ifndef WORDS_H +#define WORDS_H + +#include "misc.h" + +inline unsigned int CountWords(const word *X, unsigned int N) +{ + while (N && X[N-1]==0) + N--; + return N; +} + +inline void SetWords(word *r, word a, unsigned int n) +{ + for (unsigned int i=0; i> (WORD_BITS-shiftBits); + } + return carry; +} + +inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits) +{ + assert (shiftBits=0; i--) + { + u = r[i]; + r[i] = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + } + return carry; +} + +inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords) +{ + if (n && shiftWords) + { + for (unsigned i=n-1; i>=shiftWords; i--) + r[i] = r[i-shiftWords]; + SetWords(r, 0, STDMIN(n, shiftWords)); + } +} + +inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords) +{ + if (n && shiftWords) + { + for (unsigned i=0; i + +#ifdef DEBUG +unsigned long bits_sent; /* bit length of the compressed data */ +#endif + +// #define putbyte(b) outQ.Put(b) + +BitOutput::BitOutput(BufferedTransformation &outQ) + : outQ(outQ) +{ + bitbuff = 0; + boffset = 0; +#ifdef DEBUG + bits_sent = 0L; +#endif +} + +void BitOutput::send_bits(unsigned int value, int length) /* Send a value on a given number of bits. */ +{ +#ifdef DEBUG + assert(length > 0 && length <= 15); + assert(boffset < 8); + bits_sent += (unsigned long)length; +#endif + bitbuff |= value << boffset; + if ((boffset += length) >= 8) { + outQ.Put(bitbuff); + value >>= length - (boffset -= 8); + if (boffset >= 8) { + boffset -= 8; + outQ.Put(value); + value >>= 8; + } + bitbuff = value; + } +} + +/* Write out any remaining bits in an incomplete byte. */ +void BitOutput::bi_windup() +{ + assert(boffset < 8); + if (boffset) { + outQ.Put(bitbuff); + boffset = 0; + bitbuff = 0; +#ifdef DEBUG + bits_sent = (bits_sent+7) & ~7; +#endif + } +} + +void BitOutput::bi_putsh(word16 x) +{ + outQ.Put((byte)x); + outQ.Put(byte(x>>8)); +} + +/* Copy a stored block to the zip file, storing first the length and its + one's complement if requested. */ +void BitOutput::copy_block(byte *buf, unsigned int len, int header) +{ + /* align on byte boundary */ + bi_windup(); + + if (header) { + bi_putsh(len); + bi_putsh(~len); +#ifdef DEBUG + bits_sent += 2*16; +#endif + } + outQ.Put(buf, len); +#ifdef DEBUG + bits_sent += (unsigned long)len<<3; +#endif +} diff --git a/src/cryptlib/zbits.h b/src/cryptlib/zbits.h new file mode 100644 index 0000000..bb7645c --- /dev/null +++ b/src/cryptlib/zbits.h @@ -0,0 +1,23 @@ +#ifndef ZBITS_H +#define ZBITS_H + +#include "cryptlib.h" + +class BitOutput +{ +public: + BitOutput(BufferedTransformation &outQ); + + void send_bits (unsigned value, int length); + void bi_windup (void); + void bi_putsh (unsigned short); + void copy_block (byte *buf, unsigned len, int header); + +private: + BufferedTransformation &outQ; + unsigned bitbuff; + int boffset; +}; + +#endif + diff --git a/src/cryptlib/zdeflate.cpp b/src/cryptlib/zdeflate.cpp new file mode 100644 index 0000000..ec09ff0 --- /dev/null +++ b/src/cryptlib/zdeflate.cpp @@ -0,0 +1,594 @@ +// zdeflate.cpp - modified by Wei Dai from: +// Distributed with Jean-loup Gailly's permission. + +/* + The following sorce code is derived from Info-Zip 'zip' 2.01 + distribution copyrighted by Mark Adler, Richard B. Wales, + Jean-loup Gailly, Kai Uwe Rommel, Igor Mandrichenko and John Bush. +*/ + +/* + * deflate.c by Jean-loup Gailly. + * + * PURPOSE + * + * Identify new text as repetitions of old text within a fixed- + * length sliding window trailing behind the new text. + * + * DISCUSSION + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many info-zippers for bug reports and testing. + * + * REFERENCES + * + * APPNOTE.TXT documentation file in PKZIP 1.93a distribution. + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + */ + +#include "pch.h" +#include "zdeflate.h" +#include // for NULL + +/* Define this symbol if your target allows access to unaligned data. + * This is not mandatory, just a speed optimization. The compressed + * output is strictly identical. + */ +#ifndef UNALIGNED_OK +# ifdef MSDOS +# ifndef WIN32 +# define UNALIGNED_OK +# endif +# endif +# ifdef i386 +# define UNALIGNED_OK +# endif +# ifdef mc68020 +# define UNALIGNED_OK +# endif +# ifdef vax +# define UNALIGNED_OK +# endif +#endif + +/* Compile with MEDIUM_MEM to reduce the memory requirements or + * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the + * entire input file can be held in memory (not possible on 16 bit systems). + * Warning: defining these symbols affects HASH_BITS (see below) and thus + * affects the compression ratio. The compressed output + * is still correct, and might even be smaller in some cases. + */ + +#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH) +/* Number of bits by which ins_h and del_h must be shifted at each + * input step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * H_SHIFT * MIN_MATCH >= HASH_BITS */ + +#define max_insert_length max_lazy_match +/* Insert new strings in the hash table only if the match length + * is not greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may + * be found for specific files. */ + +const Deflator::config Deflator::configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0}, /* store only */ +/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8}, +/* 3 */ {4, 6, 32, 32}, + +/* 4 */ {4, 4, 16, 16}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32}, +/* 6 */ {8, 16, 128, 128}, +/* 7 */ {8, 32, 128, 256}, +/* 8 */ {32, 128, 258, 1024}, +/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. */ + +/* Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. */ +#define UPDATE_HASH(h,c) (h = (((h)<= 1 + */ +#ifndef ASMV +/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or + * match.s. The code is functionally equivalent, so you can use the C version + * if desired. A 68000 version is in amiga/match_68.a -- this could be used + * with other 68000 based systems such as Macintosh with a little effort. + */ +int Deflator::longest_match(IPos cur_match) +{ + unsigned chain_length = max_chain_length; /* max hash chain length */ + register byte *scan = window + strstart; /* current string */ + register byte *match; /* matched string */ + register int len; /* length of current match */ + int best_len = prev_length; /* best match length so far */ + IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + we prevent matches with the string of window index 0. */ + +/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. */ +/* +#if HASH_BITS < 8 || MAX_MATCH != 258 + #error Code too clever +#endif +*/ +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + Try with and without -DUNALIGNED_OK to check. */ + register byte *strend = window + strstart + MAX_MATCH - 1; + register word16 scan_start = *(word16*)scan; + register word16 scan_end = *(word16*)(scan+best_len-1); +#else + register byte *strend = window + strstart + MAX_MATCH; + register byte scan_end1 = scan[best_len-1]; + register byte scan_end = scan[best_len]; +#endif + + /* Do not waste too much time if we already have a good match: */ + if (prev_length >= good_match) { + chain_length >>= 2; + } + assert(strstart <= (unsigned)WINDOW_SIZE-MIN_LOOKAHEAD); + + do { + assert(cur_match < strstart); + match = window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#ifdef UNALIGNED_OK + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(word16*)(match+best_len-1) != scan_end || + *(word16*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + scan++, match++; + do { + } while (*(word16*)(scan+=2) == *(word16*)(match+=2) && + *(word16*)(scan+=2) == *(word16*)(match+=2) && + *(word16*)(scan+=2) == *(word16*)(match+=2) && + *(word16*)(scan+=2) == *(word16*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + assert(scan <= window+(unsigned)(WINDOW_SIZE-1)); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(word16*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & WMASK]) > limit + && --chain_length != 0); + + return best_len; +} +#endif /* ASMV */ + +#if defined(DEBUG) && 0 +/* Check that the match at match_start is indeed a match. */ +static void check_match(start, match, length) +IPos start, match; +int length; +{ + if (memcmp((char*)window + match, (char*)window + start, length) != 0) + { + fprintf(stderr, " start %d, match %d, length %d\n", + start, match, length); + error("invalid match"); + } + if (verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(start, match, length) +#endif + +/* Add a block of data into the window. Updates strstart and lookahead. + * IN assertion: lookahead < MIN_LOOKAHEAD. + * Note: call with either lookahead == 0 or length == 0 is valid + */ +unsigned Deflator::fill_window(const byte *buffer, unsigned int length) +{ + register unsigned n, m; + unsigned more = length; + + /* Amount of free space at the end of the window. */ + if (WINDOW_SIZE - lookahead - strstart < more) { + more = (unsigned)(WINDOW_SIZE - lookahead - strstart); + } + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= (unsigned)WSIZE+MAX_DIST) { + memcpy(window, window+(unsigned int)WSIZE, WSIZE); + match_start -= WSIZE; + strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ + + block_start -= (long) WSIZE; + + for (n = 0; n < (unsigned)HASH_SIZE; n++) { + m = head[n]; + head[n] = (Pos)(m >= (unsigned)WSIZE ? m-WSIZE : NIL); + } + for (n = 0; n < (unsigned)WSIZE; n++) { + m = prev[n]; + prev[n] = (Pos)(m >= (unsigned)WSIZE ? m-WSIZE : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + its value will never be used. */ + } + if ((more += WSIZE) > length) more = length; + } + if (more) { + memcpy((byte*)window+strstart+lookahead, buffer, more); + lookahead += more; + } + return more; +} + +/* Flush the current block, with given end-of-file flag. + IN assertion: strstart is set to the end of the current match. */ +#define FLUSH_BLOCK(eof) flush_block(block_start >= 0L ?\ + window+block_start : \ + (byte *)0, (long)strstart - block_start, (eof)) + +/* Processes a new input block. + * This function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. */ +int Deflator::fast_deflate(const byte *buffer, unsigned int length) +{ + IPos hash_head; /* head of the hash chain */ + int flush; /* set if current block must be flushed */ + unsigned accepted = 0; + + do { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. */ + accepted += fill_window(buffer+accepted, length-accepted); + if (lookahead <= minlookahead) break; + if (!uptodate) { + match_length = 0; init_hash(); uptodate = 1; + } + while (lookahead > minlookahead) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + INSERT_STRING(strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH */ + if (hash_head != NIL && strstart - hash_head <= MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + match_length = longest_match(hash_head); + /* longest_match() sets match_start */ + if (match_length > lookahead) match_length = lookahead; + } + if (match_length >= MIN_MATCH) { + check_match(strstart, match_start, match_length); + + flush = ct_tally(strstart-match_start, match_length - MIN_MATCH); + + lookahead -= match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (match_length <= max_insert_length) { + match_length--; /* string at strstart already in hash table */ + do { + strstart++; + INSERT_STRING(strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--match_length != 0); + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart]; + UPDATE_HASH(ins_h, window[strstart+1]); +/* +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif +*/ + } + } else { + /* No match, output a literal byte */ +// Tracevv((stderr,"%c",window[strstart])); + flush = ct_tally (0, window[strstart]); + lookahead--; + strstart++; + } + if (flush) { + FLUSH_BLOCK(0); + block_start = strstart; + } + } + } while (accepted < length); + if (!minlookahead) {/* eof achieved */ + FLUSH_BLOCK(1); + } + return accepted; +} + +/* Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. */ +int Deflator::lazy_deflate(const byte *buffer, unsigned int length) +{ + IPos hash_head; /* head of hash chain */ + IPos prev_match; /* previous match */ + int flush; /* set if current block must be flushed */ + register unsigned ml = match_length; /* length of best match */ +#ifdef DEBUG + extern word32 isize; /* byte length of input file, for debug only */ +#endif + unsigned accepted = 0; + + /* Process the input block. */ + do { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. */ + accepted += fill_window(buffer+accepted, length-accepted); + if (lookahead <= minlookahead) break; + if (!uptodate) { + ml = MIN_MATCH-1; /* length of best match */ + init_hash(); + uptodate = 1; + } + while (lookahead > minlookahead) { + INSERT_STRING(strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. */ + prev_length = ml, prev_match = match_start; + ml = MIN_MATCH-1; + + if (hash_head != NIL && prev_length < max_lazy_match && + strstart - hash_head <= MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + ml = longest_match (hash_head); + /* longest_match() sets match_start */ + if (ml > lookahead) ml = lookahead; + + /* Ignore a length 3 match if it is too distant: */ + if (ml == MIN_MATCH && strstart-match_start > TOO_FAR){ + /* If prev_match is also MIN_MATCH, match_start is garbage + but we will ignore the current match anyway. */ + ml--; + } + } + /* If there was a match at the previous step and the current + match is not better, output the previous match: */ + if (prev_length >= MIN_MATCH && ml <= prev_length) { + + check_match(strstart-1, prev_match, prev_length); + + flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. + */ + lookahead -= prev_length-1; + prev_length -= 2; + do { + strstart++; + INSERT_STRING(strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next lookahead bytes will always be emitted as literals. + */ + } while (--prev_length != 0); + match_available = 0; + ml = MIN_MATCH-1; + strstart++; + if (flush) { + FLUSH_BLOCK(0); + block_start = strstart; + } + + } else if (match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ +// Tracevv((stderr,"%c",window[strstart-1])); + if (ct_tally (0, window[strstart-1])) { + FLUSH_BLOCK(0), block_start = strstart; + } + strstart++; + lookahead--; + } else { + /* There is no previous match to compare with, + wait for the next step to decide. */ + match_available = 1; + strstart++; + lookahead--; + } +// assert(strstart <= isize && lookahead <= isize); + } + } while (accepted < length); + if (!minlookahead) {/* eof achieved */ + if (match_available) ct_tally (0, window[strstart-1]); + FLUSH_BLOCK(1); + } + match_length = ml; + return accepted; +} diff --git a/src/cryptlib/zdeflate.h b/src/cryptlib/zdeflate.h new file mode 100644 index 0000000..f977efa --- /dev/null +++ b/src/cryptlib/zdeflate.h @@ -0,0 +1,94 @@ +#ifndef ZDEFLATE_H +#define ZDEFLATE_H + +#include "cryptlib.h" +#include "misc.h" +#include "filters.h" +#include "ztrees.h" + +class Deflator : public Filter, private CodeTree +{ +public: + // deflate_level can be from 1 to 9, 1 being fastest, 9 being most compression + // default for the gzip program is 6 + Deflator(int deflate_level, BufferedTransformation *outQ = NULL); + + void Put(byte inByte) + {Deflator::Put(&inByte, 1);} + void Put(const byte *inString, unsigned int length); + + void InputFinished(); + +private: +#ifdef SMALL_MEM + enum {HASH_BITS=13}; +#else +# ifdef MEDIUM_MEM + enum {HASH_BITS=14}; +# else + enum {HASH_BITS=15}; +# endif +#endif + + enum {HASH_SIZE = 1< prev, head; + + unsigned fill_window (const byte*, unsigned); + void init_hash (); + + int longest_match (IPos cur_match); + + int fast_deflate(const byte *buffer, unsigned int length); + int lazy_deflate(const byte *buffer, unsigned int length); + + unsigned ins_h; /* hash index of string to be inserted */ + char uptodate; /* hash preparation flag */ + + unsigned int prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. */ + + unsigned match_start; /* start of matching string */ + unsigned lookahead; /* number of valid bytes ahead in window */ + unsigned minlookahead; + + unsigned max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this length. + * A higher limit improves compression ratio but degrades the speed. */ + + unsigned int max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. */ + + unsigned good_match; + /* Use a faster search when the previous match is longer than this */ + int nice_match; /* Stop searching when current match exceeds this */ + + /* A block of local deflate process data to be saved between + * sequential calls to deflate functions */ + int match_available; /* set if previous match exists */ + unsigned match_length; /* length of best match */ +}; + +#endif + diff --git a/src/cryptlib/zinflate.cpp b/src/cryptlib/zinflate.cpp new file mode 100644 index 0000000..6b0656c --- /dev/null +++ b/src/cryptlib/zinflate.cpp @@ -0,0 +1,881 @@ +// zinflate.cpp - modified by Wei Dai from: + +/* inflate.c -- Not copyrighted 1992 by Mark Adler + version c10p1, 10 January 1993 */ + +/* You can do whatever you like with this source file, though I would + prefer that if you modify it and redistribute it that you include + comments to that effect with your name and the date. Thank you. + [The history has been moved to the file ChangeLog.] + */ + +/* + Inflate deflated (PKZIP's method 8 compressed) data. The compression + method searches for as much of the current string of bytes (up to a + length of 258) in the previous 32K bytes. If it doesn't find any + matches (of at least length 3), it codes the next byte. Otherwise, it + codes the length of the matched string and its distance backwards from + the current position. There is a single Huffman code that codes both + single bytes (called "literals") and match lengths. A second Huffman + code codes the distance information, which follows a length code. Each + length or distance code actually represents a base value and a number + of "extra" (sometimes zero) bits to get to add to the base value. At + the end of each deflated block is a special end-of-block (EOB) literal/ + length code. The decoding process is basically: get a literal/length + code; if EOB then done; if a literal, emit the decoded byte; if a + length then get the distance and emit the referred-to bytes from the + sliding window of previously emitted data. + + There are (currently) three kinds of inflate blocks: stored, fixed, and + dynamic. The compressor deals with some chunk of data at a time, and + decides which method to use on a chunk-by-chunk basis. A chunk might + typically be 32K or 64K. If the chunk is uncompressible, then the + "stored" method is used. In this case, the bytes are simply stored as + is, eight bits per byte, with none of the above coding. The bytes are + preceded by a count, since there is no longer an EOB code. + + If the data is compressible, then either the fixed or dynamic methods + are used. In the dynamic method, the compressed data is preceded by + an encoding of the literal/length and distance Huffman codes that are + to be used to decode this block. The representation is itself Huffman + coded, and so is preceded by a description of that code. These code + descriptions take up a little space, and so for small blocks, there is + a predefined set of codes, called the fixed codes. The fixed method is + used if the block codes up smaller that way (usually for quite small + chunks), otherwise the dynamic method is used. In the latter case, the + codes are customized to the probabilities in the current block, and so + can code it much better than the pre-determined fixed codes. + + The Huffman codes themselves are decoded using a mutli-level table + lookup, in order to maximize the speed of decoding plus the speed of + building the decoding tables. See the comments below that precede the + lbits and dbits tuning parameters. + */ + +#include "pch.h" +#include "zinflate.h" +#include // for malloc and free +#include // for NULL + +const unsigned int WSIZE = 0x8000; +const unsigned long MAX_CHUNKSIZE = 0x10000L; + +Inflator::Inflator(BufferedTransformation *output, BufferedTransformation *bypassed) + : Fork(2), slide(WSIZE) +{ + SelectOutPort(1); + Attach(bypassed ? bypassed : new BitBucket); + SelectOutPort(0); + Attach(output); + + wp = 0; + bb = 0; + bk = 0; + afterEnd = false; +} + +void Inflator::Put(const byte *inString, unsigned int length) +{ + if (afterEnd) + AccessPort(1).Put(inString, length); + else + { + inQueue.Put(inString, length); + + while(!afterEnd && inQueue.CurrentSize() >= MAX_CHUNKSIZE) + inflate_block(afterEnd); + + if (afterEnd) + { + flush_output(wp); + if (bk>=8) // undo too much lookahead + AccessPort(1).Put(byte(bb>>(bk-=8))); + + inQueue.TransferTo(AccessPort(1)); + } + } +} + +void Inflator::InputFinished() +{ + while(!afterEnd && inQueue.CurrentSize()) + inflate_block(afterEnd); + + flush_output(wp); + + if (bk>=8) // undo too much lookahead + AccessPort(1).Put(byte(bb>>(bk-=8))); + + inQueue.TransferTo(AccessPort(1)); +} + +void Inflator::flush_output(unsigned int w) +{ + AccessPort(0).Put(slide, w); + wp = 0; +} + +#define memzero(x, y) memset(x, 0, y) + +# define Assert(cond,msg) assert(cond) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) + + +/* Tables for deflate from PKZIP's appnote.txt. */ +const word16 Inflator::border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +const word16 Inflator::cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +const word16 Inflator::cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +const word16 Inflator::cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +const word16 Inflator::cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed, and are initialized at the beginning of a + routine that uses these macros from a global bit buffer and count. + + If we assume that EOB will be the longest code, then we will never + ask for bits with NEEDBITS that are beyond the end of the stream. + So, NEEDBITS should not read any more bytes than are needed to + meet the request. Then no bytes need to be "returned" to the buffer + at the end of the last block. + + However, this assumption is not true for fixed blocks--the EOB code + is 7 bits, but the other literal/length codes can be 8 or 9 bits. + (The EOB code is shorter than other codes because fixed blocks are + generally short. So, while a block always has an EOB, many other + literal/length codes have a significantly lower probability of + showing up at all.) However, by making the first table have a + lookup of seven bits, the EOB code will be found in that first + lookup, and so will not require that too many bits be pulled from + the stream. + */ + + +const word16 Inflator::mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +byte Inflator::NEXTBYTE() +{ + byte b; + if (!inQueue.Get(b)) +#ifdef THROW_EXCEPTIONS + throw UnexpectedEndErr(); +#else + ; +#endif + return b; +} + +#define NEEDBITS(n) {while(k<(n)){b|=((word32)NEXTBYTE())<>=(n);k-=(n);} + + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +const int lbits = 9; /* bits in base literal/length lookup table */ +const int dbits = 6; /* bits in base distance lookup table */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be word32. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + +int Inflator::huft_build(unsigned *b, unsigned n, unsigned s, const word16 *d, const word16 *e, huft **t, int *m) +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register huft *q; /* points to current table */ + huft r; /* table entry for structure assignment */ + huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), + n-i, *p)); + c[*p]++; /* assume all entries <= BMAX */ + p++; /* Can't combine with above line (Solaris bug) */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (huft *)NULL; + *m = 0; + return 0; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (huft *)NULL; /* just to keep compilers happy */ + q = (huft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == + (struct huft *)NULL) + { + if (h) + huft_free(u[0]); + return 3; /* not enough memory */ + } + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (huft *)NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (byte)l; /* bits to dump before this table */ + r.e = (byte)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (byte)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (byte)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (word16)(*p); /* simple code is just the value */ + p++; /* one compiler does not like *p++ */ + } + else + { + r.e = (byte)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int Inflator::huft_free(huft *t) +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (huft *)NULL) + { + q = (--p)->v.t; + free((char*)p); + p = q; + } + return 0; +} + + +int Inflator::inflate_codes(huft *tl, huft *td, int bl, int bd) +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register word32 b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (byte)t->v.n; + Tracevv((stderr, "%c", slide[w-1])); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + Tracevv((stderr,"\\[%d,%d]", w-d, n)); + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + Tracevv((stderr, "%c", slide[w-1])); + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + + + +int Inflator::inflate_stored() +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register word32 b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + + /* go to byte boundary */ + n = k & 7; + DUMPBITS(n); + + + /* get the length and its complement */ + NEEDBITS(16) + n = ((unsigned)b & 0xffff); + DUMPBITS(16) + NEEDBITS(16) + if (n != (unsigned)((~b) & 0xffff)) + return 1; /* error in compressed data */ + DUMPBITS(16) + + + /* read and output the compressed data */ + while (n--) + { + NEEDBITS(8) + slide[w++] = (byte)b; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + return 0; +} + + + +int Inflator::inflate_fixed() +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + int i; /* temporary variable */ + huft *tl; /* literal/length code table */ + huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + + + /* set up literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + bl = 7; + if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) + return i; + + + /* set up distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + bd = 5; + if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) + { + huft_free(tl); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int Inflator::inflate_dynamic() +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + huft *tl; /* literal/length code table */ + huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register word32 b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in table lengths */ + NEEDBITS(5) + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ + DUMPBITS(5) + NEEDBITS(5) + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ + DUMPBITS(5) + NEEDBITS(4) + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ + DUMPBITS(4) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + + + /* free decoding table for trees */ + huft_free(tl); + + + /* restore the global bit buffer */ + bb = b; + bk = k; + + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { + if (i == 1) { +// fprintf(stderr, " incomplete literal tree\n"); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { + if (i == 1) { +// fprintf(stderr, " incomplete distance tree\n"); +#ifdef PKZIP_BUG_WORKAROUND + i = 0; + } +#else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ +#endif + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int Inflator::inflate_block(bool &e) +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register word32 b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in last block bit */ + NEEDBITS(1) + e = (int)b & 1; + DUMPBITS(1) + + + /* read in block type */ + NEEDBITS(2) + t = (unsigned)b & 3; + DUMPBITS(2) + + + /* restore the global bit buffer */ + bb = b; + bk = k; + + + int status; + + /* inflate that block type */ + switch (t) + { + case 0: + status = inflate_stored(); + break; + case 1: + status = inflate_fixed(); + break; + case 2: + status = inflate_dynamic(); + break; + default: + status = 2; + } +#ifdef THROW_EXCEPTIONS + if (status) + throw Err("Inflator: error decompressing block"); +#endif + return status; +} + diff --git a/src/cryptlib/zinflate.h b/src/cryptlib/zinflate.h new file mode 100644 index 0000000..e028f17 --- /dev/null +++ b/src/cryptlib/zinflate.h @@ -0,0 +1,63 @@ +#ifndef ZINFLATE_H +#define ZINFLATE_H + +#include "forkjoin.h" +#include "misc.h" +#include "queue.h" + +class Inflator : public Fork +{ +public: + class Err : public CryptlibException {public: Err(const char *message) : CryptlibException(message) {}}; + class UnexpectedEndErr : public Err {public: UnexpectedEndErr() : Err("Inflator: unexpected end of compressed block") {}}; + + Inflator(BufferedTransformation *output = NULL, + BufferedTransformation *bypassed = NULL); + + void Put(byte b) + {Inflator::Put(&b, 1);} + + void Put(const byte *inString, unsigned int length); + void InputFinished(); + +private: + struct huft { + byte e; /* number of extra bits or operation */ + byte b; /* number of bits in this code or subcode */ + union { + word16 n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; + }; + + int huft_build (unsigned *, unsigned, unsigned, const word16 *, const word16 *, + huft **, int *); + int huft_free (huft *); + int inflate_codes (huft *, huft *, int, int); + int inflate_stored (void); + int inflate_fixed (void); + int inflate_dynamic (void); + int inflate_block (bool &); + void flush_output(unsigned int w); + + static const word16 border[19]; + static const word16 cplens[31]; + static const word16 cplext[31]; + static const word16 cpdist[31]; + static const word16 cpdext[31]; + + static const word16 mask_bits[18]; + + ByteQueue inQueue; + byte NEXTBYTE(); + + SecByteBlock slide; + unsigned int wp; + word32 bb; /* bit buffer */ + unsigned bk; /* bits in bit buffer */ + + bool afterEnd; +}; + +#endif + diff --git a/src/cryptlib/ztrees.cpp b/src/cryptlib/ztrees.cpp new file mode 100644 index 0000000..4331575 --- /dev/null +++ b/src/cryptlib/ztrees.cpp @@ -0,0 +1,807 @@ +// ztrees.cpp - modified by Wei Dai from: +// Distributed with Jean-loup Gailly's permission. + +/* + The following sorce code is derived from Info-Zip 'zip' 2.01 + distribution copyrighted by Mark Adler, Richard B. Wales, + Jean-loup Gailly, Kai Uwe Rommel, Igor Mandrichenko and John Bush. +*/ + +/* + * trees.c by Jean-loup Gailly + * + * This is a new version of im_ctree.c originally written by Richard B. Wales + * for the defunct implosion method. + * + * PURPOSE + * + * Encode various sets of source values using variable-length + * binary code trees. + * + * DISCUSSION + * + * The PKZIP "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in the ZIP file in a compressed form + * which is itself a Huffman encoding of the lengths of + * all the code strings (in ascending order by source values). + * The actual code strings are reconstructed from the lengths in + * the UNZIP process, as described in the "application note" + * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program. + * + * REFERENCES + * + * Lynch, Thomas J. + * Data Compression: Techniques and Applications, pp. 53-55. + * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7. + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + * + * INTERFACE + * + * int ct_init (void) + * Allocate the match buffer and initialize the various tables. + * + * int ct_tally(int dist, int lc); + * Save the match info and tally the frequency counts. + * Return true if the current block must be flushed. + * + * long flush_block (char *buf, ulg stored_len, int eof) + * Determine the best encoding for the current block: dynamic trees, + * static trees or store, and output the encoded block to the zip + * file. Returns the total compressed length for the file so far. + */ + +#include "pch.h" +#include "ztrees.h" + +bool CodeTree::streesBuilt = false; +CodeTree::ct_data CodeTree::static_ltree[CodeTree::L_CODES+2]; +CodeTree::ct_data CodeTree::static_dtree[CodeTree::D_CODES]; + +const int CodeTree::extra_lbits[] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +const int CodeTree::extra_dbits[] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +const int CodeTree::extra_blbits[]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +const byte CodeTree::bl_order[] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define send_code(c, tree) send_bits(tree[(unsigned int)c].Code, tree[(unsigned int)c].Len) +/* Send a code of the given tree. c and tree must not have side effects */ + +#define d_code(dist) \ + ((dist) < 256 ? dist_code[(unsigned int)dist] : dist_code[(unsigned int)(256+((dist)>>7))]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +static unsigned reverse(unsigned int code, int len) +/* Reverse the first len bits of a code. */ +{ + register unsigned res = 0; + do res = (res << 1) | (code & 1), code>>=1; while (--len); + return res; +} + +/* Allocate the match buffer and initialize the various tables. */ +CodeTree::CodeTree(int deflate_level, BufferedTransformation &outQ) + : BitOutput(outQ), + deflate_level(deflate_level), + dyn_ltree(HEAP_SIZE), dyn_dtree(2*D_CODES+1), + bl_tree(2*BL_CODES+1), + bl_count(MAX_BITS+1), + l_desc(dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0), + d_desc(dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0), + bl_desc(bl_tree, (ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0), + heap(2*L_CODES+1), + depth(2*L_CODES+1), + length_code(MAX_MATCH-MIN_MATCH+1), + dist_code(512), + base_length(LENGTH_CODES), + base_dist(D_CODES), + l_buf(LIT_BUFSIZE), + d_buf(DIST_BUFSIZE), + flag_buf(LIT_BUFSIZE/8) +{ + + unsigned int n; /* iterates over tree elements */ + unsigned int bits; /* bit counter */ + unsigned int length; /* length value */ + register unsigned int code; /* code value */ + unsigned int dist; /* distance index */ + + compressed_len = input_len = 0L; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code=0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n=0; n < (1U< dist code (0..29) */ + dist = 0; + for (code=0 ; code < 16; code++) { + base_dist[code] = dist; + for (n=0; n < (1U<>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n=0; n < (1U<<(extra_dbits[code]-7)); n++) { + dist_code[256 + dist++] = (byte)code; + } + } + assert (dist == 256); + + if (!streesBuilt) + { + /* Construct the codes of the static literal tree */ + for (bits=0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[(unsigned int)8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[(unsigned int)9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[(unsigned int)7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[(unsigned int)8]++; + /* Codes 286 and 287 do not exist, but we must include them in the tree + construction to get a canonical Huffman tree (longest code all ones) */ + gen_codes(static_ltree, L_CODES+1); + + /* The static distance tree is trivial: */ + for (n=0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = reverse(n, 5); + } + streesBuilt = true; + } + + /* Initialize the first block of the first file: */ + init_block(); +} + +/* Initialize a new block. */ +void CodeTree::init_block() +{ + register unsigned int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n=0; n < L_CODES; n++) dyn_ltree[n].Freq = 0; + for (n=0; n < D_CODES; n++) dyn_dtree[n].Freq = 0; + for (n=0; n < BL_CODES; n++) bl_tree[n].Freq = 0; + + dyn_ltree[(unsigned int)END_BLOCK].Freq = 1; + opt_len = static_len = 0L; + last_lit = last_dist = last_flags = 0; + flags = 0; flag_bit = 1; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + +/* + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(tree, top) \ +{\ + top = heap[(unsigned int)SMALLEST]; \ + heap[(unsigned int)SMALLEST] = heap[(unsigned int)heap_len--]; \ + pqdownheap(tree, SMALLEST); \ +} + +/* + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m) \ + (tree[(unsigned int)n].Freq < tree[(unsigned int)m].Freq || \ + (tree[(unsigned int)n].Freq == tree[(unsigned int)m].Freq && depth[(unsigned int)n] <= depth[(unsigned int)m])) + +/* + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +void CodeTree::pqdownheap(ct_data *tree, int k) +{ + unsigned int kk = (unsigned int) k; + int v = heap[kk]; + unsigned int j = kk << 1; /* left son of k */ + int htemp; /* required because of bug in SASC compiler */ + + while (j <= (unsigned int)heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < (unsigned int)heap_len && smaller(tree, heap[(unsigned int)(j+1)], heap[(unsigned int)j])) j++; + + /* Exit if v is smaller than both sons */ + htemp = heap[j]; + if (smaller(tree, v, htemp)) break; + + /* Exchange v with the smallest son */ + heap[(unsigned int)k] = htemp; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + heap[(unsigned int)k] = v; +} + +/* + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +void CodeTree::gen_bitlen(tree_desc *desc) +{ + ct_data *tree = desc->dyn_tree; + const int *extra = desc->extra_bits; + int base = desc->extra_base; + int max_code = desc->max_code; + int max_length = desc->max_length; + const ct_data *stree = desc->static_tree; + unsigned int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + unsigned int bits; /* bit length */ + int xbits; /* extra bits */ + word16 f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[heap[(unsigned int)heap_max]].Len = 0; /* root of the heap */ + + for (h = heap_max+1; h < HEAP_SIZE; h++) { + n = heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > (unsigned int)max_length) bits = max_length, overflow++; + tree[n].Len = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + opt_len += (word32)f * (bits + xbits); + if (stree) static_len += (word32)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + +// Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (bl_count[bits] == 0) bits--; + bl_count[bits]--; /* move one leaf down the tree */ + bl_count[bits+1] += 2; /* move one overflow item as its brother */ + bl_count[(unsigned int)max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = bl_count[bits]; + while (n != 0) { + m = heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { +// Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq; + tree[m].Len = bits; + } + n--; + } + } +} + +/* + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +void CodeTree::gen_codes (ct_data *tree, int max_code) +{ + word16 next_code[MAX_BITS+1]; /* next code value for each bit length */ + word16 code = 0; /* running code value */ + unsigned int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->static_tree; + int elems = desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node = elems; /* next internal node of the tree */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + heap_len = 0, heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + heap[(unsigned int)++heap_len] = max_code = n; + depth[(unsigned int)n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (heap_len < 2) { + int _new = heap[(unsigned int)++heap_len] = (max_code < 2 ? ++max_code : 0); + tree[_new].Freq = 1; + depth[(unsigned int)_new] = 0; + opt_len--; if (stree) static_len -= stree[_new].Len; + /* new is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + pqremove(tree, n); /* n = node of least frequency */ + m = heap[(unsigned int)SMALLEST]; /* m = node of next least frequency */ + + heap[(unsigned int)--heap_max] = n; /* keep the nodes sorted by frequency */ + heap[(unsigned int)--heap_max] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + depth[(unsigned int)node] = (byte) (MAX(depth[(unsigned int)n], depth[(unsigned int)m]) + 1); + tree[n].Dad = tree[m].Dad = node; +#ifdef DUMP_BL_TREE + if (tree == bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + heap[(unsigned int)SMALLEST] = node++; + pqdownheap(tree, SMALLEST); + + } while (heap_len >= 2); + + heap[(unsigned int)--heap_max] = heap[(unsigned int)SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes (tree, max_code); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. Updates opt_len to take into account the repeat + * counts. (The contribution of the bit length codes will be added later + * during the construction of bl_tree.) + */ +void CodeTree::scan_tree (ct_data *tree, int max_code) +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (word16)-1; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + bl_tree[(unsigned int)curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) bl_tree[(unsigned int)curlen].Freq++; + bl_tree[(unsigned int)REP_3_6].Freq++; + } else if (count <= 10) { + bl_tree[(unsigned int)REPZ_3_10].Freq++; + } else { + bl_tree[(unsigned int)REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* Send a literal or distance tree in compressed form, + using the codes in bl_tree. */ +void CodeTree::send_tree (ct_data *tree, int max_code) +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { + send_code(curlen, bl_tree); + } while (--count != 0); + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(curlen, bl_tree); + count--; + } + assert(count >= 3 && count <= 6); + send_code(REP_3_6, bl_tree); + send_bits(count-3, 2); + } else if (count <= 10) { + send_code(REPZ_3_10, bl_tree); + send_bits(count-3, 3); + } else { + send_code(REPZ_11_138, bl_tree); + send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* Construct the Huffman tree for the bit lengths and return the index in + bl_order of the last bit length code to send. */ +int CodeTree::build_bl_tree() +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(&bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (bl_tree[(unsigned int)bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + opt_len += 3*(max_blindex+1) + 5+5+4; +// Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len)); + + return max_blindex; +} + +/* Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ +void CodeTree::send_all_trees(int lcodes, int dcodes, int blcodes) +{ + int rank; /* index in bl_order */ + + assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4); + assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES); +// Tracev((stderr, "\nbl counts: ")); + send_bits(lcodes-257, 5); + /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */ + send_bits(dcodes-1, 5); + /* not -3 as stated in appnote.txt */ + send_bits(blcodes-4, 4); + for (rank = 0; rank < blcodes; rank++) { +// Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(bl_tree[(unsigned int)bl_order[rank]].Len, 3); + } +// Tracev((stderr, "\nbl tree: sent %ld", bits_sent)); + + /* send the literal tree */ + send_tree(dyn_ltree, lcodes-1); +// Tracev((stderr, "\nlit tree: sent %ld", bits_sent)); + + /* send the distance tree */ + send_tree(dyn_dtree, dcodes-1); +// Tracev((stderr, "\ndist tree: sent %ld", bits_sent)); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. This function + * returns the total compressed length for the file so far. + */ +word32 CodeTree::flush_block(byte *buf, word32 stored_len, int eof) +{ + word32 opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex; /* index of last bit length code of non zero freq */ + + flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ + + /* Construct the literal and distance trees */ + build_tree(&l_desc); +// Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); + + build_tree(&d_desc); +// Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(); + + /* Determine the best encoding. Compute first the block length in bytes */ + opt_lenb = (opt_len+3+7)>>3; + static_lenb = (static_len+3+7)>>3; + input_len += stored_len; /* for debugging only */ + +// Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", +// opt_lenb, opt_len, static_lenb, static_len, stored_len, +// last_lit, last_dist)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + +#ifdef FORCE_METHOD + if (level == 2 && buf) /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf) /* 4: two words for the lengths */ +#endif + { + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + /* send block type */ + send_bits((STORED_BLOCK<<1)+eof, 3); + compressed_len = (compressed_len + 3 + 7) & ~7L; + compressed_len += (stored_len + 4) << 3; + /* with header */ + copy_block(buf, (unsigned)stored_len, 1); + } +#ifdef FORCE_METHOD + else if (level == 3) /* force static trees */ +#else + else if (static_lenb == opt_lenb) +#endif + { + send_bits((STATIC_TREES<<1)+eof, 3); + compress_block(static_ltree,static_dtree); + compressed_len += 3 + static_len; + } else { + send_bits((DYN_TREES<<1)+eof, 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block(dyn_ltree,dyn_dtree); + compressed_len += 3 + opt_len; + } +// assert (compressed_len == bits_sent); + init_block(); + + if (eof) { +// assert (input_len == isize); + bi_windup(); + compressed_len += 7; /* align on byte boundary */ + } +// Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3, +// compressed_len-7*eof)); + + return compressed_len >> 3; +} + +/* Save the match info and tally the frequency counts. + Return true if the current block must be flushed. */ +int CodeTree::ct_tally (int dist, int lc) +{ + l_buf[last_lit++] = (byte)lc; + if (dist == 0) { + /* lc is the unmatched char */ + dyn_ltree[(unsigned int)lc].Freq++; + } else { + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + assert((word16)dist < (word16)MAX_DIST && + (word16)lc <= (word16)(MAX_MATCH-MIN_MATCH) && + (word16)d_code(dist) < (word16)D_CODES); + + dyn_ltree[(unsigned int)length_code[(unsigned int)lc]+LITERALS+1].Freq++; + dyn_dtree[(unsigned int)d_code(dist)].Freq++; + + d_buf[last_dist++] = dist; + flags |= flag_bit; + } + flag_bit <<= 1; + + /* Output the flags if they fill a byte: */ + if ((last_lit & 7) == 0) { + flag_buf[last_flags++] = flags; + flags = 0, flag_bit = 1; + } + /* Try to guess if it is profitable to stop the current block here */ + if (deflate_level > 2 && (last_lit & 0xfff) == 0) { + /* Compute an upper bound for the compressed length */ + word32 out_length = (word32)last_lit*8L; + word32 in_length = (word32)strstart-block_start; + unsigned int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (word32)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]); + } + out_length >>= 3; +// Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", +// last_lit, last_dist, in_length, out_length, +// 100L - out_length*100L/in_length)); + if (last_dist < last_lit/2 && out_length < in_length/2) return 1; + } + return (last_lit == LIT_BUFSIZE-1 || last_dist == (unsigned)DIST_BUFSIZE); + /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. */ +} + +/* Send the block data compressed using the given Huffman trees */ +void CodeTree::compress_block(ct_data *ltree, ct_data *dtree) +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned dx = 0; /* running index in d_buf */ + unsigned fx = 0; /* running index in flag_buf */ + byte flag = 0; /* current flags */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (last_lit != 0) + do { + if ((lx & 7) == 0) flag = flag_buf[fx++]; + lc = l_buf[lx++]; + if ((flag & 1) == 0) { + /* send a literal byte */ + send_code(lc, ltree); +// Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = length_code[(unsigned int)lc]; + /* send the length code */ + send_code(code+LITERALS+1, ltree); + if ((extra = extra_lbits[code]) != 0) { + lc -= base_length[code]; + /* send the extra length bits */ + send_bits(lc, extra); + } + dist = d_buf[dx++]; + /* Here, dist is the match distance - 1 */ + code = d_code(dist); + assert(code < D_CODES); + + /* send the distance code */ + send_code(code, dtree); + if ((extra = extra_dbits[code]) != 0) { + dist -= base_dist[code]; + /* send the extra distance bits */ + send_bits(dist, extra); + } + } /* literal or match pair ? */ + flag >>= 1; + } while (lx < last_lit); + + send_code(END_BLOCK, ltree); +} diff --git a/src/cryptlib/ztrees.h b/src/cryptlib/ztrees.h new file mode 100644 index 0000000..baefbed --- /dev/null +++ b/src/cryptlib/ztrees.h @@ -0,0 +1,197 @@ +#ifndef ZTREES_H +#define ZTREES_H + +#include "misc.h" +#include "zbits.h" + +class CodeTree : private BitOutput +{ +public: + CodeTree(int deflate_level, BufferedTransformation &outQ); + + int ct_tally (int dist, int lc); + word32 flush_block (byte *buf, word32 stored_len, int eof); + + long block_start; /* window offset of current block */ + unsigned int strstart; /* window offset of current string */ + const int deflate_level; + + enum { +#ifdef SMALL_MEM + WSIZE = 0x2000, +#else +# ifdef MEDIUM_MEM + WSIZE = 0x4000, +# else + WSIZE = 0x8000, +# endif +#endif + MIN_MATCH = 3, + MAX_MATCH = 258, + MIN_LOOKAHEAD = (MAX_MATCH+MIN_MATCH+1), + MAX_DIST = (WSIZE-MIN_LOOKAHEAD) + }; + + enum { + MAX_BITS=15, + MAX_BL_BITS=7, + LENGTH_CODES=29, + LITERALS=256, + END_BLOCK=256, + L_CODES=(LITERALS+1+LENGTH_CODES), + D_CODES=30, + BL_CODES=19, + HEAP_SIZE=(2*L_CODES+1) + }; + +private: + enum { + STORED_BLOCK=0, + STATIC_TREES=1, + DYN_TREES =2 + }; + + enum { +#ifdef SMALL_MEM + LIT_BUFSIZE = 0x2000, +#else +# ifdef MEDIUM_MEM + LIT_BUFSIZE = 0x4000, +# else + LIT_BUFSIZE = 0x8000, +# endif +#endif + DIST_BUFSIZE = LIT_BUFSIZE + }; + + enum { + REP_3_6 =16, + REPZ_3_10 =17, + REPZ_11_138 =18 + }; + + static const int extra_lbits[LENGTH_CODES]; + static const int extra_dbits[D_CODES]; + static const int extra_blbits[BL_CODES]; + static const byte bl_order[BL_CODES]; + +public: + // Data structure describing a single value and its code string. */ + struct ct_data + { + union + { + word16 Freq; /* frequency count */ + word16 Code; /* bit string */ + }; + union + { + word16 Dad; /* father node in Huffman tree */ + word16 Len; /* length of bit string */ + }; + }; + +private: + SecBlock dyn_ltree, dyn_dtree; + + static ct_data static_ltree[L_CODES+2]; + /* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see ct_init + * below). + */ + + static ct_data static_dtree[D_CODES]; + /* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + + static bool streesBuilt; + + SecBlock bl_tree; + /* Huffman tree for the bit lengths */ + + SecBlock bl_count; + /* number of codes at each bit length for an optimal tree */ + + struct tree_desc + { + tree_desc(ct_data *d, ct_data *s, const int *e, int eb, int el, int ml, int mc) + : dyn_tree(d), static_tree(s), extra_bits(e), extra_base(eb), + elems(el), max_length(ml), max_code(mc) {} + ct_data *const dyn_tree; /* the dynamic tree */ + const ct_data *const static_tree; /* corresponding static tree or NULL */ + const int *extra_bits; /* extra bits for each code or NULL */ + const int extra_base; /* base index for extra_bits */ + const int elems; /* max number of elements in the tree */ + const int max_length; /* max bit length for the codes */ + int max_code; /* largest code with non zero frequency */ + }; + + tree_desc l_desc; + tree_desc d_desc; + tree_desc bl_desc; + + SecBlock heap; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + SecByteBlock depth; + /* Depth of each subtree used as tie breaker for trees of equal frequency */ + + SecByteBlock length_code; + /* length code for each normalized match length (0 == MIN_MATCH) */ + + SecByteBlock dist_code; + /* distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + + SecBlock base_length; + /* First normalized length for each code (0 = MIN_MATCH) */ + + SecBlock base_dist; + /* First normalized distance for each code (0 = distance of 1) */ + + SecByteBlock l_buf; + SecBlock d_buf; + + SecByteBlock flag_buf; + /* flag_buf is a bit array distinguishing literals from lengths in + * l_buf, and thus indicating the presence or absence of a distance. + */ + + unsigned last_lit; /* running index in l_buf */ + unsigned last_dist; /* running index in d_buf */ + unsigned last_flags; /* running index in flag_buf */ + byte flags; /* current flags not yet saved in flag_buf */ + byte flag_bit; /* current bit used in flags */ + /* bits are filled in flags starting at bit 0 (least significant). + * Note: these flags are overkill in the current code since we don't + * take advantage of DIST_BUFSIZE == LIT_BUFSIZE. + */ + + word32 opt_len; /* bit length of current block with optimal trees */ + word32 static_len; /* bit length of current block with static trees */ + word32 compressed_len; /* total bit length of compressed file */ + word32 input_len; /* total byte length of input file */ + /* input_len is for debugging only since we can get it by other means. */ + + void init_block (void); + void pqdownheap (ct_data *tree, int k); + void gen_bitlen (tree_desc *desc); + void gen_codes (ct_data *tree, int max_code); + void build_tree (tree_desc *desc); + void scan_tree (ct_data *tree, int max_code); + void send_tree (ct_data *tree, int max_code); + int build_bl_tree (void); + void send_all_trees (int lcodes, int dcodes, int blcodes); + void compress_block (ct_data *ltree, ct_data *dtree); +}; + +#endif + diff --git a/src/db/Makefile.am b/src/db/Makefile.am new file mode 100644 index 0000000..4a436e3 --- /dev/null +++ b/src/db/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libdb.a +libdb_a_SOURCES = \ + blockfile.cpp blockrecordarray.cpp blockrecordfile.cpp \ + db.cpp hierdatabase.cpp hierdbpath.cpp stddb.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libdb_a_OBJECTS) diff --git a/src/db/Makefile.in b/src/db/Makefile.in new file mode 100644 index 0000000..830f8b9 --- /dev/null +++ b/src/db/Makefile.in @@ -0,0 +1,399 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libdb_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/db +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libdb_a_AR = $(AR) $(ARFLAGS) +libdb_a_LIBADD = +am_libdb_a_OBJECTS = blockfile.$(OBJEXT) blockrecordarray.$(OBJEXT) \ + blockrecordfile.$(OBJEXT) db.$(OBJEXT) hierdatabase.$(OBJEXT) \ + hierdbpath.$(OBJEXT) stddb.$(OBJEXT) +libdb_a_OBJECTS = $(am_libdb_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libdb_a_SOURCES) +DIST_SOURCES = $(libdb_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libdb.a +libdb_a_SOURCES = \ + blockfile.cpp blockrecordarray.cpp blockrecordfile.cpp \ + db.cpp hierdatabase.cpp hierdbpath.cpp stddb.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/db/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/db/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdb.a: $(libdb_a_OBJECTS) $(libdb_a_DEPENDENCIES) + -rm -f libdb.a + $(libdb_a_AR) libdb.a $(libdb_a_OBJECTS) $(libdb_a_LIBADD) + $(RANLIB) libdb.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libdb_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/db/block.h b/src/db/block.h new file mode 100644 index 0000000..525a1fb --- /dev/null +++ b/src/db/block.h @@ -0,0 +1,201 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// block.h +// +#ifndef __BLOCK_H +#define __BLOCK_H + +#ifndef __ARCHIVE_H +#include "core/archive.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +//----------------------------------------------------------------------------- +// cBlock +//----------------------------------------------------------------------------- +template +class cBlock +{ +public: + enum { INVALID_NUM = -1 }; + + cBlock(); + + void SetDirty () { mbDirty = true; } + bool IsDirty () const { return mbDirty; } + int GetBlockNum () const { return mBlockNum; } + int8* GetData() { return mpData; } + + bool AssertValid() const; + // this asserts and returns false if the guard bytes have been corrupted + bool IsValidAddr(int8* pAddr) const; + // returns true if pAddr falls within mpData +protected: + enum { NUM_GUARD_BLOCKS = 8, // associated with BYTE_ALIGN: see ctor for info + GUARD_BLOCK_VAL = 0xAB }; // odd, non-zero value for debugging + + // guardMin and guardMax are used to detect bad writes + uint8 mGuardMin[NUM_GUARD_BLOCKS]; + int8 mpData[SIZE]; + uint8 mGuardMax[NUM_GUARD_BLOCKS]; + bool mbDirty; + int mBlockNum; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +template +inline cBlock::cBlock() +: mbDirty (false), + mBlockNum (cBlock::INVALID_NUM) +{ + // To prevent misaligned memory access, the size of the data and the + // number of guard blocks must be a multiple of the byte alignment + // and they both must be at least as large as the byte alignment + ASSERT( 0 == ( SIZE % BYTE_ALIGN ) ); + ASSERT( 0 == ( NUM_GUARD_BLOCKS % BYTE_ALIGN ) ); + ASSERT( SIZE >= BYTE_ALIGN ); + ASSERT( NUM_GUARD_BLOCKS >= BYTE_ALIGN ); + + // init guard blocks to dummy value + for( int i = 0; i < NUM_GUARD_BLOCKS; i++ ) + { + mGuardMin[i] = (uint8)GUARD_BLOCK_VAL; + mGuardMax[i] = (uint8)GUARD_BLOCK_VAL; + } + + // zero out memory + memset( mpData, 0, SIZE ); +} + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +template +inline bool cBlock::AssertValid() const +{ + // determine if guard bites have been accidentally overwritten + for( int i = 0; i < NUM_GUARD_BLOCKS; i++ ) + { + if( + ( mGuardMin[i] != (uint8) GUARD_BLOCK_VAL ) + || + ( mGuardMax[i] != (uint8) GUARD_BLOCK_VAL ) + ) + { + ASSERT( false ); + return false; + } + } + + return true; +} + +template +inline bool cBlock::IsValidAddr(int8* pAddr) const +{ + return ( (pAddr >= &mpData[0]) && (pAddr <= &mpData[SIZE-1]) ); +} + + +//----------------------------------------------------------------------------- +// cBlockImpl +//----------------------------------------------------------------------------- +template +class cBlockImpl : public cBlock +{ +public: + enum { INVALID_NUM = -1 }; + + cBlockImpl(); + + void SetBlockNum ( int blockNum ) { cBlock::mBlockNum = blockNum; } + void SetTimestamp( uint32 timestamp ) { mTimestamp = timestamp; } + uint32 GetTimestamp() const { return mTimestamp; } + + void Write ( cBidirArchive& arch ); //throw( eArchive ) + void Read ( cBidirArchive& arch, int blockNum = INVALID_NUM ); //throw( eArchive ) + // if blockNum is INVALID_NUM, then it reads in the current block number +protected: + uint32 mTimestamp; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +template +inline cBlockImpl::cBlockImpl() +: cBlock ( ), + mTimestamp (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +template +inline void cBlockImpl::Write( cBidirArchive& arch ) //throw( eArchive ) +{ + ASSERT( mbDirty ); + ASSERT( (mBlockNum >= 0) && (((mBlockNum + 1) * SIZE) <= arch.Length()) ); + + arch.Seek ( (cBlock::mBlockNum * SIZE), cBidirArchive::BEGINNING ); + arch.WriteBlob ( cBlock::mpData, SIZE ); + + cBlock::mbDirty = false; +} + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +template +inline void cBlockImpl::Read( cBidirArchive& arch, int blockNum ) //throw( eArchive ) +{ + if( blockNum != INVALID_NUM ) + cBlock::mBlockNum = blockNum; + + ASSERT( (mBlockNum >= 0) && (((mBlockNum + 1) * SIZE) <= arch.Length()) ); + +// std::cout << "cBlockImpl::Read() mBlockNum = " << mBlockNum << " arch.Length() = " << arch.Length() << std::endl; + + arch.Seek ( (cBlock::mBlockNum * SIZE), cBidirArchive::BEGINNING ); + arch.ReadBlob ( cBlock::mpData, SIZE ); + + cBlock::mbDirty = false; +} + +#endif + diff --git a/src/db/blockfile.cpp b/src/db/blockfile.cpp new file mode 100644 index 0000000..b0679b2 --- /dev/null +++ b/src/db/blockfile.cpp @@ -0,0 +1,362 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockfile.cpp + +#include "stddb.h" + +#ifndef __TCHAR_H +#error +#endif + +#include "blockfile.h" +#include "core/archive.h" +#include "core/debug.h" +#include "core/archive.h" + +#include + +//----------------------------------------------------------------------------- +// cBlockFile +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cBlockFile::cBlockFile() +: mNumPages (-1), + mNumBlocks (-1), + mTimer (0), + mpArchive (0) +{ +#ifdef _BLOCKFILE_DEBUG + + mNumBlockWrite = 0; + mNumBlockRead = 0; + mNumPageFault = 0; + mNumPageRequests = 0; + +#endif //_BLOCKFILE_DEBUG +} + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cBlockFile::~cBlockFile() +{ + Close(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Open +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::Open( const TSTRING& fileName, int numPages, bool bTruncate) //throw (eArchive) +{ + ASSERT( numPages > 0 ); + ASSERT( ! mpArchive ); + + cFileArchive* pArch = new cFileArchive; + pArch->OpenReadWrite( fileName.c_str(), ( bTruncate ? cFileArchive::FA_OPEN_TRUNCATE : 0 ) ); + + Open( pArch, numPages ); +} + +void cBlockFile::Open( cBidirArchive* pArch, int numPages ) //throw (eArchive) +{ + ASSERT( numPages > 0 ); + ASSERT( ! mpArchive ); + // + // keep my sanity... + // + pArch->Seek( 0, cBidirArchive::BEGINNING ); + // + // initialize the paged blocks list... + // + mpArchive = pArch; + mNumPages = numPages; + mvPagedBlocks.resize( mNumPages ); + ASSERT( mvPagedBlocks.capacity() == mNumPages ); // make sure that we didn't alloc too many! + // + // if the file is newly created, set its size to that of a single block + // + if( mpArchive->Length() == 0 ) + { + mpArchive->WriteBlob( mvPagedBlocks[0].GetData(), GetBlockSize() ); + } + // + // make sure that the file is an appropriate length + // TODO -- what is the correct thing to do if this fails? right now, I assert, but + // perhaps I should throw an exception or increase the file size to the next block interval + ASSERT( mpArchive->Length() % GetBlockSize() == 0 ); + mNumBlocks = mpArchive->Length() / GetBlockSize(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Close +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::Close() +{ + if( mpArchive ) + { + Flush(); + delete mpArchive; + mpArchive = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Flush +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::Flush() +{ + ASSERT( mpArchive ); + for( BlockVector::iterator i = mvPagedBlocks.begin(); i != mvPagedBlocks.end(); i++ ) + { + FlushBlock( &(*i) ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// GetBlock +/////////////////////////////////////////////////////////////////////////////// +cBlockFile::Block* cBlockFile::GetBlock( int blockNum ) //throw (eArchive) +{ +#ifdef _BLOCKFILE_DEBUG + mNumPageRequests++; + AssertValid(); +#endif + // + // debug stuff + // + cDebug d( "cBlockFile::GetBlock" ); + d.TraceNever( "Request for block %d\n", blockNum ); + + //TODO -- I should really throw an exception here... + ASSERT( (blockNum >= 0) && (blockNum < GetNumBlocks()) ); + ASSERT( mpArchive ); + + // + // first, increment the timer; if it flips, reset everybody's access times to 0. + // + mTimer++; + if( mTimer == 0 ) + { + for( BlockVector::iterator i = mvPagedBlocks.begin(); i != mvPagedBlocks.end(); i++ ) + { + i->SetTimestamp( 0 ); + } + } + // + // now, see if the desired block is in memory... + // + for( BlockVector::iterator i = mvPagedBlocks.begin(); i != mvPagedBlocks.end(); i++ ) + { + if( i->GetBlockNum() == blockNum ) + { + // this is easy; just return the block. + i->SetTimestamp( mTimer ); + d.TraceNever( "\tBlock %d was in memory.\n", blockNum ); + return &(*i); + } + } + // + // ok, we are going to have to page it into memory; look for the page with the earliest timestamp to + // remove... + // +#ifdef _BLOCKFILE_DEBUG + mNumPageFault++; +#endif + d.TraceNever( "\tBlock %d was not in memory; paging it in\n", blockNum ); + + uint32 earliestTime = mvPagedBlocks[0].GetTimestamp(); + BlockVector::iterator it = mvPagedBlocks.begin(); + BlockVector::iterator earliestIter = it; + it++; // since we don't want to check the first one + ASSERT(it != mvPagedBlocks.end()); + for( ; it != mvPagedBlocks.end(); it++ ) + { + if( it->GetTimestamp() < earliestTime ) + { + earliestIter = it; + earliestTime = it->GetTimestamp(); + } + } + ASSERT( (earliestIter >= mvPagedBlocks.begin()) && (earliestIter < mvPagedBlocks.end()) ); + // + // flush the page data to disk if it is dirty... + // + FlushBlock( &(*earliestIter) ); + d.TraceNever( "\tPaging out block %d\n", earliestIter->GetBlockNum() ); + // + // ok, now we can read in the new page... + // + earliestIter->SetBlockNum ( blockNum ); + earliestIter->Read ( *mpArchive ); + earliestIter->SetTimestamp ( mTimer ); + // + // this variable keeps track of how many block reads we do. +#ifdef _BLOCKFILE_DEBUG + mNumBlockRead++; + AssertValid(); +#endif + return &(*earliestIter); + +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateBlock +/////////////////////////////////////////////////////////////////////////////// +cBlockFile::Block* cBlockFile::CreateBlock() +{ + // debug stuff + // + ASSERT( mpArchive ); + cDebug d( "cBlockFile::CreateBlock()" ); + d.TraceDetail( "Creating new block (number %d)\n", GetNumBlocks() ); + + char emptyBlock[BLOCK_SIZE]; + memset( emptyBlock, 0, BLOCK_SIZE ); + // + // write empty data in the new block's location + // + //ASSERT(GetNumBlocks() * GetBlockSize() <= mpArchive->Length()); + d.TraceDetail("Seeking to %d * %d = %d\n", GetNumBlocks(), GetBlockSize(), GetNumBlocks() * GetBlockSize()); + mpArchive->Seek ( GetNumBlocks() * GetBlockSize(), cBidirArchive::BEGINNING ); + mpArchive->WriteBlob ( emptyBlock, BLOCK_SIZE ); + // + // now, page it in... + // + mNumBlocks++; + return GetBlock( GetNumBlocks() - 1 ); +} + +/////////////////////////////////////////////////////////////////////////////// +// DestroyLastBlock +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::DestroyLastBlock( ) +{ + //TODO -- implement this!!! + ASSERT( false ); +/* + mNumBlocks--; + mpArchive->Seek( mNumBlocks * BLOCK_SIZE, cBidirArchive::BEGINNING ); + mpArchive->Truncate(); + + AssertValid(); +*/ +} + + +//----------------------------------------------------------------------------- +// Debug methods... +//----------------------------------------------------------------------------- +#ifdef _BLOCKFILE_DEBUG + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::TraceContents(int dl) const +{ + cDebug d( "cBlockFile::TraceContents" ); + if( dl == -1 ) + dl = cDebug::D_DEBUG; + + d.Trace( dl, "Block size: %d\n", GetBlockSize() ); + d.Trace( dl, "Number of blocks: %d\n", mNumBlocks ); + d.Trace( dl, "Current timer: %d\n", mTimer ); + // + // trace out the profiling info... + // + d.Trace( dl, "Number of page writes: %d\n", mNumBlockWrite ); + d.Trace( dl, "Number of page reads: %d\n", mNumBlockRead ); + d.Trace( dl, "Number of page faults: %d\n", mNumPageFault ); + d.Trace( dl, "Number of page requests:%d\n", mNumPageRequests ); + + d.Trace( dl, "Number of pages: %d\n", mNumPages ); + d.Trace( dl, "-------------------------\n"); + // + // trace out all the block information... + // + int cnt = 0; + for( BlockVector::const_iterator i = mvPagedBlocks.begin(); i != mvPagedBlocks.end(); i++, cnt++ ) + { + d.Trace( dl, "Page[%d] Block Num=%d Timestamp=%d Dirty=%s\n", cnt, i->GetBlockNum(), i->GetTimestamp(), i->IsDirty() ? "true" : "false"); + } + d.Trace( dl, "-------------------------\n"); + +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateBlock +/////////////////////////////////////////////////////////////////////////////// +void cBlockFile::AssertValid() const +{ + if( ! mpArchive ) + return; + // + // make sure the archive length and block count match up + // + #ifdef _DEBUG + if (mpArchive->Length() != (GetBlockSize() * GetNumBlocks())) + { + cDebug d("cBlockFile::AssertValid"); + d.Trace(cDebug::D_DEBUG, "FATAL ERROR!!!\n"); + d.Trace(cDebug::D_DEBUG, "mpArchive->Length() = %d \n\t!= blocksize * numblocks = %d * %d\n", int(mpArchive->Length()), int(GetBlockSize()), int(GetNumBlocks())); + d.Trace(cDebug::D_DEBUG, "now tracing the contents...\n"); + TraceContents(cDebug::D_DEBUG); + } + #endif + ASSERT( mpArchive->Length() == (GetBlockSize() * GetNumBlocks()) ); + + // + // iterate through the pages... + // + for( BlockVector::const_iterator i = mvPagedBlocks.begin(); i != mvPagedBlocks.end(); i++) + { + // make sure the block number is valid + // + int blockNum = i->GetBlockNum(); + ASSERT( (blockNum == cBlock::INVALID_NUM) || + ( (blockNum >= 0) && (blockNum < GetNumBlocks()) ) ); + // + // make sure the time stamp is less than or equal to the timer time... + // + ASSERT( i->GetTimestamp() <= mTimer ); + // + // assert that the guard bytes haven't been modified + i->AssertValid(); + } +} + +#endif //_BLOCKFILE_DEBUG + diff --git a/src/db/blockfile.h b/src/db/blockfile.h new file mode 100644 index 0000000..48cb6db --- /dev/null +++ b/src/db/blockfile.h @@ -0,0 +1,155 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockfile.h +// +// cBlockFile -- +#ifndef __BLOCKFILE_H +#define __BLOCKFILE_H + +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __BLOCK_H +#include "block.h" +#endif + +#ifdef _DEBUG +#undef _BLOCKFILE_DEBUG // If we dont do this, test does not compile on unix +#define _BLOCKFILE_DEBUG // If we dont do this, test does not compile on unix +#endif + +class cBlockFile_i; +class eArchive; +class cBidirArchive; +//----------------------------------------------------------------------------- +// cBlockFile +//----------------------------------------------------------------------------- +class cBlockFile +{ +public: + enum { BLOCK_SIZE = 4096 }; + typedef cBlock Block; + + cBlockFile(); + ~cBlockFile(); + + void Open( const TSTRING& fileName, int numPages, bool bTruncate = false ); //throw (eArchive) + // opens the given file name as a block file, and uses numPages to signify the + // number of pages to cache blocks in as they are accessed from disk. + // if bTruncate is true, then the file is created with zero length. + void Open( cBidirArchive* pArch, int numPages ); //throw (eArchive) + // the same as the previous Open(), except the passed in archive is used. This class will destroy + // the archive when it is done (when Close() is called). If the archive length is zero, then + // we create a new database. Otherwise, we assume we are opening an existing file. + void Close(); //throw (eArchive) + // writes all unsaved data to disk and disassociates the block file from its archive + void Flush(); //throw (eArchive) + // flushes all dirty data to disk + + Block* GetBlock( int blockNum ); //throw (eArchive) + // returns the specified block. This asserts that the block number is below GetNumBlocks() + // this method takes care of paging the block into memory and returns a pointer to the block. + + Block* CreateBlock(); //throw (eArchive) + // this creates a new block, sets its number to GetNumBlocks(), pages it into memory, and + // returns a pointer to it + + void DestroyLastBlock( ); + // this method removes the last block from the file + + int GetNumBlocks() const { return mNumBlocks; } + int GetBlockSize() const { return BLOCK_SIZE; } + + cBidirArchive* GetArchive() { return mpArchive; } + // NOTE -- be _very_ careful with this archive. It should probably not be written to +private: + typedef cBlockImpl BlockImpl; + typedef std::vector< BlockImpl > BlockVector; + + int mNumPages; + int mNumBlocks; // the total number of blocks in the archive. + uint32 mTimer; // keeps track of the current "time" + cBidirArchive* mpArchive; // note: I always own the deletion of the archive + BlockVector mvPagedBlocks; + + void FlushBlock( BlockImpl* pBlock ); //throw (eArchive) + // helper function that writes a block to disk if it is dirty + + /////////////////////////////////////////////////////////////////////////// + // Profiling / Debugging interface + /////////////////////////////////////////////////////////////////////////// +#ifdef _BLOCKFILE_DEBUG +public: + void TraceContents(int dl = -1) const; + // traces out all the info we can on the current state of this class + // dl is the debug level to trace it at; -1 means to use D_DEBUG + void AssertValid() const; + // ASSERTs as much as we can about the consistancy of our internal state. + int mNumBlockWrite; + // counts how many writes we have done + int mNumBlockRead; + // counts how many reads we have done + int mNumPageFault; + // number of times a page fault occured + int mNumPageRequests; + // number of page requests (useful to compare with mNumPageFault) + +#endif //_BLOCKFILE_DEBUG + +}; + + +//############################################################################# +// inline implementation +//############################################################################# +inline void cBlockFile::FlushBlock( cBlockFile::BlockImpl* pBlock ) //throw (eArchive) +{ + + if( (pBlock->GetBlockNum() != Block::INVALID_NUM) && pBlock->IsDirty() ) + { + // mNumBlockWrite keeps track of how many block writes we do + // +#ifdef _BLOCKFILE_DEBUG + mNumBlockWrite++; +#endif + + pBlock->Write( *mpArchive ); + } +} + + +#endif //__BLOCKFILE_H + diff --git a/src/db/blockfile_t.cpp b/src/db/blockfile_t.cpp new file mode 100644 index 0000000..170473d --- /dev/null +++ b/src/db/blockfile_t.cpp @@ -0,0 +1,119 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// blockfile_t +#include "stddb.h" +#include "blockfile.h" +#include "block.h" +#include "core/archive.h" +#include "test/test.h" +#include "core/debug.h" + +void TestBlockFile() +{ + cDebug d( "TestBlockFile" ); + + try + { + static const TCHAR fileName[] = _T("c:/tmp/test.bf"); + // truncate the file I am going to use... + // + cFileArchive a; + a.OpenReadWrite( fileName ); + a.Close(); + // + // open up the block file... + // + cBlockFile bf; + bf.Open( fileName, 2 ); // opened up with two pages + #ifdef _BLOCKFILE_DEBUG + bf.TraceContents(); + #endif + + // get a block and write something to it... + // + cBlockFile::Block* pB = bf.GetBlock( 0 ); + TEST( pB ); + static const TCHAR str1[] = _T("Block 1"); + memcpy( pB->GetData(), str1, sizeof(str1) ); + pB->SetDirty(); + #ifdef _BLOCKFILE_DEBUG + bf.TraceContents(); + #endif + + // get another block... + // + pB = bf.CreateBlock(); + TEST( pB ); + static const TCHAR str2[] = _T("Block 2"); + memcpy( pB->GetData(), str2, sizeof(str2) ); + pB->SetDirty(); + #ifdef _BLOCKFILE_DEBUG + bf.TraceContents(); + #endif + + // get the first block we wrote... + // + pB = bf.GetBlock( 0 ); + TEST( pB ); + *pB->GetData() = _T('F'); + #ifdef _BLOCKFILE_DEBUG + bf.TraceContents(); + #endif + + // + // create a third block -- someone will have to be paged out in order for this to happen + // + pB = bf.CreateBlock(); + TEST( pB ); + static const TCHAR str3[] = _T("Block 3"); + memcpy( pB->GetData(), str3, sizeof(str3) ); + pB->SetDirty(); + #ifdef _BLOCKFILE_DEBUG + bf.TraceContents(); + #endif + + // + // test the guard bytes... + /* + memcpy( pB->GetData() + (cBlockFile::BLOCK_SIZE - 4), str3, sizeof(str3) ); + memcpy( pB->GetData() - 1, str3, sizeof(str3) ); + pB->AssertValid(); + */ + + bf.Close(); + } + catch( eError& e ) + { + d.TraceError( _T("Exception caught: %d %s\n"), e.GetID(), e.GetMsg().c_str() ); + TEST( false ); + } +} diff --git a/src/db/blockrecordarray.cpp b/src/db/blockrecordarray.cpp new file mode 100644 index 0000000..56ff4a2 --- /dev/null +++ b/src/db/blockrecordarray.cpp @@ -0,0 +1,610 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockrecordarray.cpp + +#include "stddb.h" + +#include "blockrecordarray.h" + + +/////////////////////////////////////////////////////////////////////////////// +// util_GetIndexArray -- returns a reference to the index array inside a block +// Right now, this is just a cast, but if the blocks ever had headers, this +// would also take that offset into account +/////////////////////////////////////////////////////////////////////////////// +inline cBlockRecordArray::tIndexArray& util_GetIndexArray(cBlockFile::Block* pBlock) +{ + return (* reinterpret_cast( pBlock->GetData() ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// util_OffsetToAddr -- given an offset from the end of a block (such as +// is stored in tRecordIndex) return a pointer to memory inside the block +// that corresponds to the given offset +/////////////////////////////////////////////////////////////////////////////// +inline int8* util_OffsetToAddr(cBlockFile::Block* pBlock, int offset) +{ + return ( pBlock->GetData() + (cBlockFile::BLOCK_SIZE - offset) ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cBlockRecordArray::cBlockRecordArray(cBlockFile* pBlockFile, int blockNum) +: mpBlockFile ( pBlockFile ), + mBlockNum ( blockNum ), + mSpaceAvailable ( -1 ), + mNumItems ( 0 ), + mbInit ( false ) +{ +} + +cBlockRecordArray::cBlockRecordArray() +: mpBlockFile ( 0 ), + mBlockNum ( -1 ), + mSpaceAvailable ( -1 ), + mNumItems ( 0 ), + mbInit ( false ) +{ +} + +void cBlockRecordArray::Init(cBlockFile* pBlockFile, int blockNum) +{ + ASSERT(! pBlockFile ); + + mpBlockFile = pBlockFile; + mBlockNum = blockNum; + mSpaceAvailable = -1; + mNumItems = 0; + mbInit = false; +} + + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cBlockRecordArray::~cBlockRecordArray() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// InitNewBlock +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::InitNewBlock() //throw (eArchive) +{ + ASSERT( mpBlockFile != 0); + ASSERT( (mBlockNum >= 0) && (mBlockNum < mpBlockFile->GetNumBlocks()) ); +#ifdef _BLOCKFILE_DEBUG + mpBlockFile->AssertValid(); +#endif + + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& array = util_GetIndexArray( pBlock ); + // + // set everything to zero.. + // + memset( pBlock->GetData(), 0, cBlockFile::BLOCK_SIZE ); + pBlock->SetDirty(); + // + // set up the guard byte for the index array... + // + array.maRecordIndex[0].SetOffset ( -1 ); + array.maRecordIndex[0].SetMainIndex ( INVALID_INDEX ); + // + // remember that we have been initialized + // + mbInit = true; + // + // update the free space and max index variables... + // + mNumItems = 0; + UpdateFreeSpace( pBlock ); + WriteHeaderInfo( pBlock ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// InitForExistingBlock +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::InitForExistingBlock() //throw (eArchive) +{ + ASSERT( mpBlockFile != 0); + ASSERT( (mBlockNum >= 0) && (mBlockNum < mpBlockFile->GetNumBlocks()) ); + ASSERT( ! mbInit ); + // + // read in our header info... + // + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + ReadHeaderInfo(pBlock); + // + // remember that we have been initialized + // + mbInit = true; + // + // some debug out... + // + cDebug d("cBlockRecordArray::InitForExistingBlock"); + d.TraceDetail(" Executed for block %d; NumItems=%d, SpaceAvail=%d\n", mBlockNum, mNumItems, mSpaceAvailable); +} + + +/////////////////////////////////////////////////////////////////////////////// +// WriteHeaderInfo +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::WriteHeaderInfo(cBlockFile::Block* pBlock) +{ + ASSERT( mpBlockFile != 0); + ASSERT( Initialized() ); + + util_GetIndexArray(pBlock).mHeader.SetNumItems ( mNumItems ); + util_GetIndexArray(pBlock).mHeader.SetSpaceAvail( mSpaceAvailable ); + + pBlock->SetDirty(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadHeaderInfo +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::ReadHeaderInfo (cBlockFile::Block* pBlock) +{ + ASSERT( mpBlockFile != 0); + + mNumItems = util_GetIndexArray(pBlock).mHeader.GetNumItems(); + mSpaceAvailable = util_GetIndexArray(pBlock).mHeader.GetSpaceAvail(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// UpdateFreeSpace +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::UpdateFreeSpace(cBlockFile::Block* pBlock) +{ + ASSERT( Initialized() ); + ASSERT( mpBlockFile != 0); + // first, take into account the size of all of the index structures. Note that + // we add one to the current number because we want to account for the new one + // that might be added if another item were added to the array + // + int availSpace = cBlockFile::BLOCK_SIZE - sizeof(tHeader) - ( (GetNumItems() + 1) * sizeof(tRecordIndex) ); + // + // always take the MARGIN away, to give ourselves some breathing room between the indexes and + // the data + // + availSpace -= MARGIN; + // + // subtract from availSpace the amount of room that the actual data is taking up... + // note that it is always true that the top index points to a valid value + // + if( GetNumItems() > 0 ) + { + int topOffset = util_GetIndexArray(pBlock).maRecordIndex[ GetNumItems()-1 ].GetOffset(); + availSpace -= topOffset; + } + + mSpaceAvailable = availSpace < 0 ? 0 : availSpace ; + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// IsItemValid +/////////////////////////////////////////////////////////////////////////////// +bool cBlockRecordArray::IsItemValid(int index) const //throw (eArchive) +{ + ASSERT( Initialized() ); + + if ( (index < 0) || (index >= GetNumItems()) ) + return false; + + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + + return (util_GetIndexArray(pBlock).maRecordIndex[ index ].GetMainIndex() != INVALID_INDEX ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddItem +/////////////////////////////////////////////////////////////////////////////// +int cBlockRecordArray::AddItem(int8* pData, int dataSize, int mainIndex) //throw (eArchive) +{ + // make ourselves initialized, if we are not right now... + // + if( ! Initialized() ) + { + InitForExistingBlock(); + } + + + ASSERT( dataSize <= GetAvailableSpace() ); + ASSERT( GetNumItems() <= MAX_RECORDS ); + ASSERT( dataSize > 0 ); // I am not sure if this is the right thing to do ! + ASSERT( mpBlockFile != 0); + ASSERT( mainIndex != INVALID_INDEX ); + ASSERT( Initialized() ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); +#endif + cDebug d("cBlockRecordArray::AddItem"); + d.TraceDetail( "Entering... adding item of size %d to block %d\n", dataSize, mBlockNum ); + // + // get the block we need and a reference into the index array.... + // + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& indexArray = util_GetIndexArray(pBlock); + // + // find an unused entry to put the item into... + // + tRecordIndex* pIndex = indexArray.maRecordIndex; + int newIndex = 0; + for( ; newIndex < mNumItems; newIndex++, pIndex++ ) + { + if( pIndex->GetMainIndex() == INVALID_INDEX ) + break; + } + d.TraceDetail( "Adding new item to index %d (max index + 1 = %d)\n", newIndex, mNumItems ); + // write the data we know for sure at this point... + // + pIndex->SetMainIndex( mainIndex ); + pBlock->SetDirty(); + // + // calculate the offset for the new data + // + int prevOffset = ( newIndex == 0 ? 0 : indexArray.maRecordIndex[ newIndex-1 ].GetOffset() ); + pIndex->SetOffset( prevOffset + dataSize ); + + if( newIndex == mNumItems ) + { + // + // increment the max number of indexes... + // + mNumItems++; + indexArray.maRecordIndex[ mNumItems ].SetOffset ( -1 ); + indexArray.maRecordIndex[ mNumItems ].SetMainIndex ( INVALID_INDEX ); + } + else + { + // we are going to have to shift up the data that is above us... + // + int topOffset = indexArray.maRecordIndex[GetNumItems()-1].GetOffset(); + int8* pTop = util_OffsetToAddr( pBlock, topOffset ); + int amtToMove = topOffset - prevOffset; + ASSERT( amtToMove >= 0 ); + + memmove( pTop - dataSize, pTop, amtToMove ); + // + // now, we need to iterate over all of the existing entries, updating their offsets... + // + tRecordIndex* pMovedIndex = pIndex + 1; + for( int i = newIndex + 1; i < mNumItems; i++, pMovedIndex++ ) + { + pMovedIndex->SetOffset( pMovedIndex->GetOffset() + dataSize ); + } + + } + // + // write the data... + // + memcpy( util_OffsetToAddr( pBlock, pIndex->GetOffset() ), pData, dataSize ); + // + // update the free space... + // + indexArray.maRecordIndex[ mNumItems ].SetOffset ( -1 ); + indexArray.maRecordIndex[ mNumItems ].SetMainIndex ( INVALID_INDEX ); + UpdateFreeSpace( pBlock ); + WriteHeaderInfo( pBlock ); + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); + d.TraceDetail( "*** Add Complete; here are the new contents ***\n"); + TraceContents( cDebug::D_NEVER ); +#endif + + return newIndex; +} + +/////////////////////////////////////////////////////////////////////////////// +// DeleteItem +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::DeleteItem(int index) //throw (eArchive) +{ + // make ourselves initialized, if we are not right now... + // + if( ! Initialized() ) + { + InitForExistingBlock(); + } + + + ASSERT( mpBlockFile != 0); + ASSERT( IsItemValid(index) ); + ASSERT( Initialized() ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); +#endif + cDebug d("cBlockRecordArray::DeleteItem"); + d.TraceDetail( "Entering... Removing item index %d from block %d\n", index, mBlockNum); + + // + // get the block we need and a reference into the index array.... + // + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& indexArray = util_GetIndexArray(pBlock); + pBlock->SetDirty(); + // + // if this is the last entry, then our job is easy... + // + if( (index + 1) == mNumItems ) + { + mNumItems--; + // we need to clean out all the entries that are empty at the end of the index list... + // + while( (mNumItems > 0) && (indexArray.maRecordIndex[ mNumItems-1 ].GetMainIndex() == INVALID_INDEX) ) + { + mNumItems--; + } + // + // set the guard bytes... + // + indexArray.maRecordIndex[ mNumItems ].SetOffset ( -1 ); + indexArray.maRecordIndex[ mNumItems ].SetMainIndex ( INVALID_INDEX ); + } + else + { + // we are going to shift all entries above the deleted entry down; + // first, figure out how far we are shifting and the source address... + // + int sizeToShift = indexArray.maRecordIndex[GetNumItems()-1].GetOffset() - indexArray.maRecordIndex[index].GetOffset(); + int distToShift = indexArray.maRecordIndex[index].GetOffset(); + if( index > 0 ) + { + distToShift -= indexArray.maRecordIndex[index - 1].GetOffset(); + } + int8* pSrc = util_OffsetToAddr( pBlock, indexArray.maRecordIndex[GetNumItems()-1].GetOffset() ); + // + // copy the data.. + // + ASSERT ( pBlock->IsValidAddr(pSrc) && pBlock->IsValidAddr(pSrc + distToShift + sizeToShift - 1) ); + ASSERT ( sizeToShift >= 0 ); + ASSERT ( distToShift >= 0 ); + memmove ( pSrc + distToShift, pSrc, sizeToShift ); + // + // mark this entry as unused... + // note that the offset is set to be the same as the item before it. + // + tRecordIndex* pIndex = &indexArray.maRecordIndex[ index ]; + pIndex->SetMainIndex ( INVALID_INDEX ); + pIndex->SetOffset ( (index == 0 ? 0 : indexArray.maRecordIndex[ index-1 ].GetOffset()) ); + // + // now, iterate over the items, moving their offsets down... + // + pIndex++; + for( int i = index+1; i < GetNumItems(); i++, pIndex++ ) + { + pIndex->SetOffset( pIndex->GetOffset() - distToShift ); + } + } + + UpdateFreeSpace( pBlock ); + WriteHeaderInfo( pBlock ); + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); + d.TraceDetail( "*** Removal Complete; here are the new contents ***\n"); + TraceContents( cDebug::D_NEVER ); +#endif + +} + +/////////////////////////////////////////////////////////////////////////////// +// GetDataForReading +/////////////////////////////////////////////////////////////////////////////// +int8* cBlockRecordArray::GetDataForReading( int index, int32& dataSize ) //throw (eArchive) +{ + // make ourselves initialized, if we are not right now... + // + if( ! Initialized() ) + { + InitForExistingBlock(); + } + + ASSERT( IsItemValid(index) ); + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& indexArray = util_GetIndexArray(pBlock); + // + // figure out the size of the block + // + dataSize = indexArray.maRecordIndex[index].GetOffset(); + if( index != 0 ) + { + dataSize -= indexArray.maRecordIndex[index-1].GetOffset(); + } + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); +#endif + + + return( util_OffsetToAddr(pBlock, indexArray.maRecordIndex[index].GetOffset()) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetDataForWriting +/////////////////////////////////////////////////////////////////////////////// +int8* cBlockRecordArray::GetDataForWriting( int index, int32& dataSize ) //throw (eArchive) +{ + // make ourselves initialized, if we are not right now... + // + if( ! Initialized() ) + { + InitForExistingBlock(); + } + + ASSERT( IsItemValid(index) ); + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& indexArray = util_GetIndexArray(pBlock); + pBlock->SetDirty(); + // + // figure out the size of the block + // + dataSize = indexArray.maRecordIndex[index].GetOffset(); + if( index != 0 ) + { + dataSize -= indexArray.maRecordIndex[index-1].GetOffset(); + } + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); + mpBlockFile->AssertValid(); +#endif + + return( util_OffsetToAddr(pBlock, indexArray.maRecordIndex[index].GetOffset()) ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// IsClassValid +/////////////////////////////////////////////////////////////////////////////// +#define BRA_ASSERT(x) if(x) ; else { ASSERT(false); return false; } + +bool cBlockRecordArray::IsClassValid() const +{ + ASSERT( mpBlockFile != 0); + cDebug d( "cBlockRecordArray::AssertValid" ); + if( ! mbInit ) + { + // if we haven't been initialized yet, then I assume that we are valid... + // + return true; + } + + // + // get the block we need and a reference into the index array.... + // + try + { + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& array = util_GetIndexArray(pBlock); + // + // make sure that the num items and available space make sense... + // + BRA_ASSERT( (mNumItems >= 0) && (mNumItems <= MAX_RECORDS) ); + BRA_ASSERT( (mSpaceAvailable >= 0) && (mSpaceAvailable <= MAX_DATA_SIZE) ); + // + // assert that the top index points to a valid value... + // + if(mNumItems != 0) + { + BRA_ASSERT( array.maRecordIndex[mNumItems-1].GetMainIndex() != INVALID_INDEX ); + BRA_ASSERT( array.maRecordIndex[mNumItems-1].GetOffset() != -1 ); + } + + int prevOff = 0; + int i; + for( i = 0; i < mNumItems; i++ ) + { + BRA_ASSERT( array.maRecordIndex[i].GetOffset() >= prevOff ); + prevOff = array.maRecordIndex[i].GetOffset(); + } + // make sure the guard byte is there... + // + BRA_ASSERT( array.maRecordIndex[i].GetOffset() == -1 ); + // + // make sure the final offset is less than the highest record index offset. + // + BRA_ASSERT( (int8*)&array.maRecordIndex[i] < util_OffsetToAddr( pBlock, prevOff ) ); + // + // TODO -- is there anything else that is worth checking? + + } + catch( eArchive& e ) + { + d.TraceError( "*** cBlockFile::GetBlock threw an eArchive: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + BRA_ASSERT( false ); + } + // if we got here, then everything worked ok. + // + return true; +} + + + +#ifdef _BLOCKFILE_DEBUG + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::TraceContents(int dl) const +{ + if( dl == -1 ) + dl = cDebug::D_DEBUG; + + cDebug d( "cBlockRecordArray::TraceContents" ); + + d.Trace( dl, "---------- Block Record Array ----------\n" ); + d.Trace( dl, "----------------------------------------\n" ); + d.Trace( dl, "Block Number %d\n", mBlockNum ); + d.Trace( dl, "Space Available %d\n", mSpaceAvailable ); + d.Trace( dl, "Num Entries %d\n", mNumItems); + + cBlockFile::Block* pBlock = mpBlockFile->GetBlock( mBlockNum ); + tIndexArray& indexArray = util_GetIndexArray(pBlock); + + for( int i=0; i < mNumItems; i++ ) + { + d.Trace( dl, "(%d)\tOffset %d\tMain Idx %d\n", i, indexArray.maRecordIndex[i].GetOffset(), indexArray.maRecordIndex[i].GetMainIndex() ); + } + + d.Trace( dl, "----------------------------------------\n" ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// AssertValid +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordArray::AssertValid() const +{ + ASSERT( IsClassValid() ); +} + +#endif + diff --git a/src/db/blockrecordarray.h b/src/db/blockrecordarray.h new file mode 100644 index 0000000..8f79ecc --- /dev/null +++ b/src/db/blockrecordarray.h @@ -0,0 +1,202 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockrecordarray.h +// +// cBlockRecordArray +// +#ifndef __BLOCKRECORDARRAY_H +#define __BLOCKRECORDARRAY_H + +#ifndef __BLOCKFILE_H +#include "blockfile.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +// +// TODO -- I need to guarantee that all of the structures in this class do not have any pad bytes. +// This is true under win32, but I am not sure if it will always be true. -- 10 feb 99 mdb +// + +class eArchive; + +class cBlockRecordArray +{ +public: + //------------------------------------------------------------------------------------- + // Construction + //------------------------------------------------------------------------------------- + cBlockRecordArray(cBlockFile* pBlockFile, int blockNum); + // this object is associated with a single block in a cBlockFile. It is _not_ + // asserted that the blockNum is valid for the associated file at this point, + // since it is possible that the file has not been loaded yet + cBlockRecordArray(); + // if this version of the ctor is called, then Init() must be called before it can be used. + void Init(cBlockFile* pBlockFile, int blockNum); + + virtual ~cBlockRecordArray(); + + //------------------------------------------------------------------------------------- + // Initialization ... exactly one of these methods must be called before this class can be used + //------------------------------------------------------------------------------------- + void InitNewBlock() ; //throw (eArchive) + // this method should be called when a new block has been created, and before this + // class operates on it. + void InitForExistingBlock() ; //throw (eArchive) + // this method should be called to initialize this class for use with a block that has + // previously been created and initialized with InitNewBlock(). + + //------------------------------------------------------------------------------------- + // Data Manipulation + //------------------------------------------------------------------------------------- + int AddItem(int8* pData, int dataSize, int mainIndex) ; //throw (eArchive) + // inserts the given item into the array; returns the index that it was inserted into. + // this asserts that there is room for the new element, and updates the avail. space and + // max index as necessary. + void DeleteItem(int index ) ; //throw (eArchive) + // deletes the specified item; this asserts that the index is valid, and updates the avail. + // space and max index as necessary. + int8* GetDataForReading( int index, int32& dataSize ) ; //throw (eArchive) + // returns a pointer to the named data. This method will assert that the address is + // valid. The data pointer returned is guarenteed to be valid only until the next + // method call into this class. + int8* GetDataForWriting( int index, int32& dataSize ) ; //throw (eArchive) + // this is the same as the previous function, except the dirty bit for the page is also set + bool IsItemValid(int index) const ; //throw (eArchive) + // returns true if the given index has a valid value. + + bool IsClassValid() const; + // returns true if the class has an internally consistant state. If an archive exception + // occurs, false is returned. This method is good for determining if a newly opened block + // file is actually a block file + + bool Initialized() const { return mbInit; } + int GetAvailableSpace() const { ASSERT( Initialized() ); return mSpaceAvailable; } + int GetNumItems() const { ASSERT( Initialized() ); return mNumItems; } + // returns the number of items currently being stored in the array + + /////////////////////////////////////////////////////////////////// + // tRecordIndex -- this is what each record in the array is + // indexed by. These come at the beginning of the block and + // the record data comes at the end. + /////////////////////////////////////////////////////////////////// + struct tRecordIndex + { + private: + int32 mOffset; // offset from the end of the block that my data is at; offset 1 is the last byte in the block + int32 mMainIndex; // my main array index + public: + // byte order safe access methods... + // + void SetOffset ( int32 off ) { mOffset = tw_htonl( off ); } + int32 GetOffset ( ) { return tw_ntohl( mOffset ); } + void SetMainIndex ( int32 idx ) { mMainIndex= tw_htonl( idx ); } + int32 GetMainIndex ( ) { return tw_ntohl( mMainIndex ); } + }; + /////////////////////////////////////////////////////////////////// + // tHeader -- the info that appears at the beginning of the block + /////////////////////////////////////////////////////////////////// + struct tHeader + { + private: + int32 mSpaceAvailable; + int32 mNumItems; + public: + // byte order safe access methods... + // + void SetSpaceAvail ( int32 sa ) { mSpaceAvailable = tw_htonl( sa ); } + int32 GetSpaceAvail ( ) { return tw_ntohl( mSpaceAvailable ); } + void SetNumItems ( int32 ni ) { mNumItems = tw_htonl( ni ); } + int32 GetNumItems ( ) { return tw_ntohl( mNumItems ); } + }; + + enum { MAX_RECORDS = cBlockFile::BLOCK_SIZE / ( sizeof(tRecordIndex) + sizeof(uint32) ), + // MAX_RECORDS signifies the maximum number of records that can be stored in a single block. + // It is rationalized like this: each used record needs a tRecordIndex plus an extra uint32 + // as a minimum storage requirement (even though it is ok to have a record that is filled in + // with zero bytes) + MARGIN = 10 , + // MARGIN is the min. amount of room that should exist between the indexes and the data. This + // is used when calculating the available space, and also in assertions. + MAX_DATA_SIZE = cBlockFile::BLOCK_SIZE - sizeof(tRecordIndex) - sizeof(tHeader) - MARGIN, + // this is the largest single piece of data that could theoreticaly be stored (if it were the + // only thing stored in the block). We assume that the single record index will take up space, + // the header will take up space, and the margin will take up space. + INVALID_INDEX = -1 + // when tRecordIndex::mMainIndex is set to this, it indicates that the index is not being used. + }; + + /////////////////////////////////////////////////////////////////// + // tIndexArray -- the beginning of a block is treated + // as one of these + /////////////////////////////////////////////////////////////////// + struct tIndexArray + { + tHeader mHeader; + tRecordIndex maRecordIndex[MAX_RECORDS]; + }; + +private: + cBlockFile* mpBlockFile; + int mBlockNum; // the block that I am operating on + int mSpaceAvailable; // amount of storage I have left + int mNumItems; // number of items currently being stored in this array + bool mbInit; // has InitXXX() been called? + + void UpdateFreeSpace(cBlockFile::Block* pBlock); + // calculates the total free space available in this array and assigns + // it to mSpaceAvailable. Note that the value of mSpaceAvailable signifies + // the size of the largest single item that could be added to the array. + void WriteHeaderInfo(cBlockFile::Block* pBlock); + // gets the header information at the top of our block in sync with our member vars + void ReadHeaderInfo (cBlockFile::Block* pBlock); + // reads the header info from the block and sets our member vars to what was read + + /////////////////////////////////////////////////////////////////////////// + // Profiling / Debugging interface + /////////////////////////////////////////////////////////////////////////// +#ifdef _BLOCKFILE_DEBUG +public: + void TraceContents(int dl = -1) const; + // traces out all the info we can on the current state of this class + // dl is the debug level to trace it at; -1 means to use D_DEBUG + void AssertValid() const; + // ASSERTs as much as we can about the consistency of our internal state. +#endif +}; + + + +#endif //__BLOCKRECORDARRAY_H + diff --git a/src/db/blockrecordarray_t.cpp b/src/db/blockrecordarray_t.cpp new file mode 100644 index 0000000..c77068e --- /dev/null +++ b/src/db/blockrecordarray_t.cpp @@ -0,0 +1,134 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// blockrecordarray_t.cpp + +#include "stddb.h" +#include "db/blockrecordarray.h" +#include "test/test.h" +#include "core/debug.h" +#include "core/error.h" + +void TestBlockRecordArray() +{ + cDebug d( "TestBlockRecordArray" ); + try + { + static const TCHAR fileName[] = _T("c:/tmp/test.bf"); + + cBlockFile bf; + bf.Open( fileName, 2, true ); // opened up with two pages + + // make sure the file is large enough... + // + while( bf.GetNumBlocks() < 2 ) + { + bf.CreateBlock(); + } + + // create the record arrays and associate them with the two blocks... + // + cBlockRecordArray ra1( &bf, 0 ); ra1.InitNewBlock(); + cBlockRecordArray ra2( &bf, 1 ); ra2.InitNewBlock(); + // + // now, start adding and removing things from the arrays... + // + static const char data1[] = "This is data 1"; + static const char data2[] = "And here we have data 2"; + static const char data3[] = "Here is d a t a 3!"; + static const char data4[] = "Three cheers for data 4!"; + ra1.AddItem( (int8*)data1, sizeof(data1), 1 ); + ra1.AddItem( (int8*)data2, sizeof(data2), 2 ); + ra1.AddItem( (int8*)data3, sizeof(data3), 3 ); + ra1.AddItem( (int8*)data4, sizeof(data4), 4 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // TODO -- try deleting the second to last and then the last thing from the array to + // see if we clean up properly. + + // delete item 2... + ra1.DeleteItem( 1 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // add a new item... + static const char data5[] = "fffiiivvveee!"; + ra1.AddItem( (int8*)data5, sizeof(data5), 5 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // delete the second to last and last items to see if we clean up properly... + // note that there are four things here at this point. + ra1.DeleteItem( 2 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + ra1.DeleteItem( 3 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // delete the first item to see if that works ok.... + ra1.DeleteItem( 0 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // add a couple more just for kicks :-) + static const char data6[] = "We're looking for six"; + static const char data7[] = "All 7s go to heaven"; + ra1.AddItem( (int8*)data6, sizeof(data6), 6 ); + ra1.AddItem( (int8*)data7, sizeof(data7), 7 ); + #ifdef _BLOCKFILE_DEBUG + ra1.TraceContents(); + #endif + + // Now, we will close the file, reopen it and see if we can read it ok. + // + bf.Close(); + bf.Open( fileName, 2, false ); + cBlockRecordArray ra3( &bf, 0 ); ra3.InitForExistingBlock(); + d.TraceDebug( "\n------ Tracing out the contents of the first block after being read back in from disk...\n\n"); + #ifdef _BLOCKFILE_DEBUG + ra3.TraceContents(); + #endif + } + catch( eError& e ) + { + d.TraceError( "Exception caught: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + TEST( false ); + } +} + diff --git a/src/db/blockrecordfile.cpp b/src/db/blockrecordfile.cpp new file mode 100644 index 0000000..d9752ea --- /dev/null +++ b/src/db/blockrecordfile.cpp @@ -0,0 +1,341 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockrecordfile.cpp + +#include "stddb.h" + +#include "blockrecordfile.h" +#include "core/archive.h" + +/////////////////////////////////////////////////////////////////////////////// +// util_InitBlockArray +/////////////////////////////////////////////////////////////////////////////// +static inline void util_InitBlockArray( cBlockRecordArray& block ) +{ + if( ! block.Initialized() ) + { + block.InitForExistingBlock(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cBlockRecordFile::cBlockRecordFile() +: mLastAddedTo( -1 ), + mbOpen ( false ) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cBlockRecordFile::~cBlockRecordFile() +{ + Close(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Open +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::Open ( const TSTRING& fileName, int numPages, bool bTruncate) //throw (eArchive) +{ + ASSERT( ! mbOpen ); + + // first, open the file.. + // + mBlockFile.Open( fileName, numPages, bTruncate ); +} + +void cBlockRecordFile::Open( cBidirArchive* pArch, int numPages ) //throw (eArchive) +{ + ASSERT( ! mbOpen ); + bool bTruncate = ( pArch->Length() == 0 ); + + mBlockFile.Open( pArch, numPages ); + + OpenImpl( bTruncate ); +} + +/////////////////////////////////////////////////////////////////////////////// +// OpenImpl +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::OpenImpl( bool bTruncate ) //throw (eArchive) +{ + ASSERT( ! mbOpen ); + // + // create the vector of block record arrays...avoid initializing them all + // right now so that we don't page the whole file into memory + // + mvBlocks.clear(); + for( int i=0; i < mBlockFile.GetNumBlocks(); i++ ) + { + mvBlocks.push_back( cBlockRecordArray( &mBlockFile, i ) ); + // + // if we are creating a new file, initialize the block for first usage... + // + if( bTruncate ) + { + mvBlocks.back().InitNewBlock(); + } + } + // + // use the integrity of the first block as a q&d check for file integrity... + // + ASSERT( mvBlocks.size() > 0 ); + if(! mvBlocks.begin()->Initialized() ) + { + mvBlocks.begin()->InitForExistingBlock(); + } + if( ! mvBlocks.begin()->IsClassValid() ) + { + TSTRING str = _T("Bad file format for the Block Record File"); + throw eArchiveFormat( str ); + } + // set the last item added to to zero (TODO -- is this the right thing to do or + // should I store it in the archive? + // + mLastAddedTo = 0; + + mbOpen = true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Close +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::Close() //throw (eArchive) +{ + Flush(); + mBlockFile.Close(); + mbOpen = false; + mvBlocks.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Flush +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::Flush() //throw (eArchive) +{ + mBlockFile.Flush(); +} + +/////////////////////////////////////////////////////////////////////////////// +// AddItem +/////////////////////////////////////////////////////////////////////////////// +cBlockRecordFile::tAddr cBlockRecordFile::AddItem( int8* pData, int dataSize ) //throw (eArchive) +{ + ASSERT( mbOpen ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + tAddr rtn(0, 0); + // + // first, let's find room for this data item... + // + rtn.mBlockNum = FindRoomForData( dataSize ); + // + // now, insert the data... + // + rtn.mIndex = mvBlocks[rtn.mBlockNum].AddItem( pData, dataSize, 1 ); + // + // update the last added to pointer and return the location... + // + mLastAddedTo = rtn.mBlockNum; + return rtn; +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveItem +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::RemoveItem( cBlockRecordFile::tAddr dataAddr ) //throw (eArchive) +{ + ASSERT( mbOpen ); + ASSERT( IsValidAddr( dataAddr ) ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + + mvBlocks[ dataAddr.mBlockNum ].DeleteItem( dataAddr.mIndex ); + // + // remove unneeded blocks at the end... + // + //TODO -- not implemented yet! + /* + while( mvBlocks.back().GetNumItems() == 0 ) + { + // if there are >2 blocks, and the back two blocks are both + // empty, remove one. We always want to be sure there is at + // least one block in the database, and we don't want to remove + // single trailing empty blocks because it would perform poorly if + // there were a bunch of additions and removals at the end of the file. + if( (mvBlocks.size() > 2) && (mvBlocks[ mvBlocks.size()-2 ].GetNumItems() == 0 ) + { + // TODO -- uncomment these to implement file shrinking... + mvBlocks.pop_back(); + mBlockFile.DestroyLastBlock(); + } + } + */ +} + +/////////////////////////////////////////////////////////////////////////////// +// IsValidAddr +/////////////////////////////////////////////////////////////////////////////// +bool cBlockRecordFile::IsValidAddr( cBlockRecordFile::tAddr addr ) //throw (eArchive) +{ + ASSERT( mbOpen ); + + if( (addr.mBlockNum < 0) || (addr.mBlockNum >= mBlockFile.GetNumBlocks()) ) + return false; + + util_InitBlockArray( mvBlocks[ addr.mBlockNum ] ); + + return ( mvBlocks[ addr.mBlockNum ].IsItemValid( addr.mIndex ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetDataForReading +/////////////////////////////////////////////////////////////////////////////// +int8* cBlockRecordFile::GetDataForReading( cBlockRecordFile::tAddr dataAddr, int32& dataSize ) //throw (eArchive) +{ + ASSERT( mbOpen ); + ASSERT( IsValidAddr( dataAddr ) ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + + return ( mvBlocks[ dataAddr.mBlockNum ].GetDataForReading( dataAddr.mIndex, dataSize ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetDataForWriting +/////////////////////////////////////////////////////////////////////////////// +int8* cBlockRecordFile::GetDataForWriting( cBlockRecordFile::tAddr dataAddr, int32& dataSize ) //throw (eArchive) +{ + ASSERT( mbOpen ); + ASSERT( IsValidAddr( dataAddr ) ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + + return ( mvBlocks[ dataAddr.mBlockNum ].GetDataForWriting( dataAddr.mIndex, dataSize ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// FindRoomForData +/////////////////////////////////////////////////////////////////////////////// +int cBlockRecordFile::FindRoomForData( int32 dataSize ) //throw (eArchive) +{ + ASSERT( (dataSize > 0) && (dataSize <= cBlockRecordArray::MAX_DATA_SIZE) ); + ASSERT( mbOpen ); +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + cDebug d("cBlockRecordFile::FindRoomForData"); + + // first, try the last added to block... + // + d.TraceDetail( "Looking for room for %d bytes; first trying mLastAddedTo (%d)\n", dataSize, mLastAddedTo ); + util_InitBlockArray( mvBlocks[mLastAddedTo] ); + if( mvBlocks[mLastAddedTo].GetAvailableSpace() >= dataSize ) + { + d.TraceDetail( "---Found room in block %d\n", mLastAddedTo ); + return mLastAddedTo; + } + // + // ok, I guess we will have to iterate through all the blocks... + // + BlockArray::iterator it; + int cnt = 0; + for( it = mvBlocks.begin(); it != mvBlocks.end(); it++, cnt++ ) + { + util_InitBlockArray( *it ); + if( it->GetAvailableSpace() >= dataSize ) + { + d.TraceDetail( "---Found room in block %d\n", cnt ); + return cnt; + } + } + // + // if we got here, then we need to add a new block + // + d.TraceDetail( "---We need to add new block(%d)\n", cnt); + mBlockFile.CreateBlock(); + ASSERT( (mBlockFile.GetNumBlocks() == (mvBlocks.size()+1)) && (mvBlocks.size() == cnt) ); + mvBlocks.push_back( cBlockRecordArray( &mBlockFile, cnt ) ); + mvBlocks.back().InitNewBlock(); + + ASSERT( mvBlocks.back().GetAvailableSpace() >= dataSize ); + + return cnt; +} + + +#ifdef _BLOCKFILE_DEBUG + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::TraceContents(int dl) const +{ + // TODO -- this is probably not what I want to do, but it helps me right now... + // + for( BlockArray::const_iterator i = mvBlocks.begin(); i != mvBlocks.end(); i++ ) + { + i->TraceContents( dl ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// AssertValid +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::AssertValid() const +{ + ASSERT( (mLastAddedTo >= 0) && (mLastAddedTo < mvBlocks.size()) ); + ASSERT( mvBlocks.size() == mBlockFile.GetNumBlocks() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AssertAllBlocksValid +/////////////////////////////////////////////////////////////////////////////// +void cBlockRecordFile::AssertAllBlocksValid() +{ + for( BlockArray::iterator i = mvBlocks.begin(); i != mvBlocks.end(); i++ ) + { + i->AssertValid(); + } +} + + +#endif + diff --git a/src/db/blockrecordfile.h b/src/db/blockrecordfile.h new file mode 100644 index 0000000..aaa0711 --- /dev/null +++ b/src/db/blockrecordfile.h @@ -0,0 +1,156 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// blockrecordfile.h +// +#ifndef __BLOCKRECORDFILE_H +#define __BLOCKRECORDFILE_H + +#ifndef __BLOCKFILE_H +#include "blockfile.h" +#endif +#ifndef __BLOCKRECORDARRAY_H +#include "blockrecordarray.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +#ifndef __ERROR_H +#include "core/error.h" +#endif + +class eArchive; + +class cBlockRecordFile +{ +public: + //------------------------------------------------------------------------- + // Construction and Destruction + //------------------------------------------------------------------------- + cBlockRecordFile(); + virtual ~cBlockRecordFile(); + + //------------------------------------------------------------------------- + // Opening and Closing Files + //------------------------------------------------------------------------- + virtual void Open ( const TSTRING& fileName, int numPages, bool bTruncate = false ) ; //throw (eArchive) + virtual void Open ( cBidirArchive* pArch, int numPages ) ; //throw (eArchive) + // for the second Open(), this class owns the destruction of the archive + virtual void Close () ; //throw (eArchive) + virtual void Flush () ; //throw (eArchive) + + //------------------------------------------------------------------------- + // tAddr -- struct that is used to identify the location of a data item in + // the file + //------------------------------------------------------------------------- + struct tAddr + { + int32 mBlockNum; + int32 mIndex; + + tAddr(int32 block = -1, int32 addr = -1) : mBlockNum(block), mIndex(addr) {} + }; + + //------------------------------------------------------------------------- + // Adding and Removing Data + //------------------------------------------------------------------------- + tAddr AddItem( int8* pData, int dataSize ) ; //throw (eArchive) + // adds the given data to the file, growing it as necessary. Return value + // can be used in the future to retrieve the data + void RemoveItem( tAddr dataAddr ) ; //throw (eArchive) + // removes the named data from the file. This will assert that the given + // address is valid, and will shrink the end of the file if there are + // empty blocks at the end after the removal TODO -- it doesn't actually + // do the latter. + + //------------------------------------------------------------------------- + // Accessing Data + //------------------------------------------------------------------------- + bool IsValidAddr( tAddr addr ) ; //throw (eArchive) + // returns true if the given address points to valid data + int8* GetDataForReading( tAddr dataAddr, int32& dataSize ) ; //throw (eArchive) + // returns a pointer to the named data. This method will assert that the address is + // valid. The data pointer returned is guarenteed to be valid only until the next + // method call into this class. + int8* GetDataForWriting( tAddr dataAddr, int32& dataSize ) ; //throw (eArchive) + // this is the same as the previous function, except the dirty bit for the page is also set + + cBidirArchive* GetArchive() { return mBlockFile.GetArchive(); } + // NOTE -- be very careful with this; only read from it and do not write to it. + + //------------------------------------------------------------------------- + // Private Implementation + //------------------------------------------------------------------------- +protected: + typedef std::vector BlockArray; + // + // NOTE -- use all of these methods with much care! + // + cBlockFile* GetBlockFile () { return &mBlockFile; } + BlockArray* GetBlockArray () { return &mvBlocks; } + +private: + + int32 mLastAddedTo; // optimization that keeps track of last block added to + bool mbOpen; // are we currently associated with a file? + cBlockFile mBlockFile; + BlockArray mvBlocks; + + cBlockRecordFile ( const cBlockRecordFile& rhs ); //not impl + void operator= ( const cBlockRecordFile& rhs ); //not impl + + int FindRoomForData( int32 dataSize ); //throw (eArchive) + // searches through all the blocks, starting with mLastAddedTo, looking + // for one with dataSize free space. This asserts that the size is valid + // for storage in a block + void OpenImpl( bool bTruncate ); //throw (eArchive) + // implementation of the Open() methods above; both end up calling this. + + //------------------------------------------------------------------------- + // Profiling / Debugging Interface + //------------------------------------------------------------------------- +#ifdef _BLOCKFILE_DEBUG +public: + void TraceContents(int dl = -1) const; + // traces out all the info we can on the current state of this class + // dl is the debug level to trace it at; -1 means to use D_DEBUG + void AssertValid() const; + // ASSERTs as much as we can about the consistancy of our internal state. + void AssertAllBlocksValid() ; + // time consuming function that calls AssertValid() on all of the blocks +#endif + +}; + + +#endif //__BLOCKRECORDFILE_H + diff --git a/src/db/db.cpp b/src/db/db.cpp new file mode 100644 index 0000000..dfdd680 --- /dev/null +++ b/src/db/db.cpp @@ -0,0 +1,51 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: db.cpp +// Date....: 7/13/99 +// Creator.: Brian McFeely (bmcfeely) +// +// +#include "stddb.h" +#include "db.h" +#include "core/core.h" // for: TSS_Package( cCore ) + +TSS_ImplementPackage( cDb ) + +cDb::cDb() +{ + TSS_Dependency( cCore ); +} + + +// eof: db.cpp + diff --git a/src/db/db.h b/src/db/db.h new file mode 100644 index 0000000..a284f68 --- /dev/null +++ b/src/db/db.h @@ -0,0 +1,58 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: db.h +// Date....: 05/11/99 +// Creator.: rdifalco +// +// + +#ifndef __DB_H +#define __DB_H + +//--Include Core Platform Declarations + +#include "core/package.h" // for: Packaging Abstraction + +//--Classes + +TSS_BeginPackage( cDb ) + + public: + + cDb(); + +TSS_EndPackage( cDb ) + + +#endif //__DB_H + diff --git a/src/db/dberrors.cpp b/src/db/dberrors.cpp new file mode 100644 index 0000000..822159e --- /dev/null +++ b/src/db/dberrors.cpp @@ -0,0 +1,53 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////// +// dberrors.cpp +// +// Registers all error strings in the db package +// + +#include "stddb.h" +#include "core/errortable.h" + +#include "hierdatabase.h" + +TSS_BEGIN_ERROR_REGISTRATION( db ) + +// +// HierDatabase +// + +TSS_REGISTER_ERROR( eHierDatabase(), _T("Database Error.") ) +TSS_REGISTER_ERROR( eHierDbInternal(), _T("Internal database error.") ) +TSS_REGISTER_ERROR( eHierDbDupeName(), _T("Attempt to add duplicate name to database.") ) + +TSS_END_ERROR_REGISTRATION() diff --git a/src/db/hierdatabase.cpp b/src/db/hierdatabase.cpp new file mode 100644 index 0000000..05e94a6 --- /dev/null +++ b/src/db/hierdatabase.cpp @@ -0,0 +1,763 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// hierdatabase.cpp + +#include "stddb.h" + +#include "hierdatabase.h" +#include "hierdbnode.h" +#include "core/archive.h" +#include "core/upperbound.h" +#include "core/errorbucket.h" + +// TODO -- all of these util_ functions should throw an eArchive if an attempt is made to +// write to a null address + +static inline void util_ThrowIfNull( const cHierAddr& addr, const TSTRING& context ) +{ + ASSERT( ! addr.IsNull() ); + if( addr.IsNull() ) + { + TSTRING msg(_T("Attempt to access null address")); + if( ! context.empty() ) + { + msg += _T(" in ") + context; + } + throw eHierDatabase( msg ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// util_ReadObject -- this will read the given object from the database from the +// given address. eArchive is thrown on exception. +/////////////////////////////////////////////////////////////////////////////// +static void util_ReadObject( cHierDatabase* pDb, cHierNode* pNode, const cHierAddr& addr ) +{ + int32 dataSize; + int8* pData = pDb->GetDataForReading( cBlockRecordFile::tAddr(addr.mBlockNum, addr.mIndex), dataSize ); + // + // make sure we aren't trying to read a null object + // + util_ThrowIfNull( addr, _T("util_ReadObject") ); + + cFixedMemArchive arch( pData, dataSize ); + pNode->Read( arch ); +} + +/////////////////////////////////////////////////////////////////////////////// +// util_WriteObject -- this will write the given object to the database, returning +// the address that it was written to, and throwing eArchive on error. +/////////////////////////////////////////////////////////////////////////////// +static cHierAddr util_WriteObject( cHierDatabase* pDb, cHierNode* pNode ) +{ + static cMemoryArchive arch; + arch.Seek( 0, cBidirArchive::BEGINNING ); + pNode->Write( arch ); + + cBlockRecordFile::tAddr addr = pDb->AddItem( arch.GetMemory(), arch.CurrentPos() ); + return cHierAddr( addr.mBlockNum, addr.mIndex ); +} + +/////////////////////////////////////////////////////////////////////////////// +// util_RewriteObject -- call this when the data in a structure has changed, but +// its size has not; this will update the database without changing the +// object's address. +/////////////////////////////////////////////////////////////////////////////// +static void util_RewriteObject( cHierDatabase* pDb, cHierNode* pNode, const cHierAddr& addr ) +{ + int32 dataSize; + int8* pData = pDb->GetDataForWriting( cBlockRecordFile::tAddr(addr.mBlockNum, addr.mIndex), dataSize ); + + util_ThrowIfNull( addr, _T("util_RewriteObject") ); + + cFixedMemArchive arch( pData, dataSize ); + pNode->Write( arch ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cHierDatabase::cHierDatabase( bool bCaseSensitive, TCHAR delChar ) +: mRootArrayAddr (), + mbCaseSensitive ( bCaseSensitive ), + mDelimitingChar ( delChar ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cHierDatabase::~cHierDatabase() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// Open +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabase::Open ( cBidirArchive* pArch, int numPages ) //throw (eArchive, eHierDatabase) +{ + bool bTruncate = ( pArch->Length() == 0 ); + inherited::Open( pArch, numPages ); + + OpenImpl( bTruncate ); +} + + +void cHierDatabase::Open ( const TSTRING& fileName, int numPages, bool bTruncate ) //throw (eArchive, eHierDatabase) +{ + inherited::Open(fileName, numPages, bTruncate); + +#ifdef _BLOCKFILE_DEBUG + AssertValid(); +#endif + + OpenImpl( bTruncate ); +} + +/////////////////////////////////////////////////////////////////////////////// +// OpenImpl +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabase::OpenImpl ( bool bTruncate ) //throw (eArchive, eHierDatabase) +{ + // now, we should write the root node at (0,0) if we are creating, and assert that the root node + // is there if we are opening an existing one... + // + if( bTruncate ) + { + // + // make the root node that we are creating... + // + cHierRoot rootNode; + rootNode.mChild = cHierAddr( 0, 1 ); // the first array will be placed at (0,1) + rootNode.mbCaseSensitive = mbCaseSensitive; + rootNode.mDelimitingChar = mDelimitingChar; + cHierAddr addr = util_WriteObject( this, &rootNode ); + // + // assert that it was written to (0, 0) + // + ASSERT( (addr.mBlockNum == 0) && (addr.mIndex == 0) ); + // + // make an empty array to serve as the root array. + // + cHierArrayInfo arrayInfo; + arrayInfo.mParent = cHierAddr(); + arrayInfo.mArray = cHierAddr(); + // + // actually write the objects and assert that they were written to the right places. + // + addr = util_WriteObject( this, &arrayInfo ); + ASSERT( (addr.mBlockNum == 0) && (addr.mIndex == 1) ); + + mRootArrayAddr = cHierAddr( 0, 1 ); + } + else + { + cHierRoot rootNode; + util_ReadObject( this, &rootNode, cHierAddr( 0, 0 ) ); + // + // set the location of the top-level array and the other root parameters... + // + mRootArrayAddr = rootNode.mChild; + mbCaseSensitive = rootNode.mbCaseSensitive; + mDelimitingChar = rootNode.mDelimitingChar; + } +} + +//----------------------------------------------------------------------------- +// cHierDatabaseIter +//----------------------------------------------------------------------------- + +cHierDatabaseIter::cHierDatabaseIter( cHierDatabase* pDb ) //throw(eArchive) +: mpDb ( pDb ), + mCurPath( ) +{ + ASSERT( pDb != 0); + mCurPath.SetCaseSensitive ( mpDb->IsCaseSensitive() ); + mCurPath.SetDelimiter ( mpDb->GetDelimitingChar() ); + // + // load in the root array... + // + SeekToRoot(); +} + +cHierDatabaseIter::~cHierDatabaseIter() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekToRoot +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::SeekToRoot() //throw (eArchive) +{ + ASSERT( mpDb != 0); + ASSERT( ! mpDb->mRootArrayAddr.IsNull() ); + mCurPath.Clear(); + LoadArrayAt( mpDb->mRootArrayAddr ); +} + +/////////////////////////////////////////////////////////////////////////////// +// copy ctor +/////////////////////////////////////////////////////////////////////////////// +cHierDatabaseIter::cHierDatabaseIter( const cHierDatabaseIter& rhs ) +{ + *this = rhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +cHierDatabaseIter& cHierDatabaseIter::operator=( const cHierDatabaseIter& rhs ) +{ + mpDb = rhs.mpDb; + mEntries = rhs.mEntries; + mInfo = rhs.mInfo; + mInfoAddr = rhs.mInfoAddr; + mCurPath = rhs.mCurPath; + // + // the iterator is a little trickier + // + if( rhs.Done() ) + { + mIter = mEntries.end(); + } + else + { + EntryArray::const_iterator p1, p2; + p1 = rhs.mIter; + p2 = rhs.mEntries.begin(); + mIter = mEntries.begin() + (p1 - p2); + } + + return (*this); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LoadArrayAt +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::LoadArrayAt(const cHierAddr& addr) //throw (eArchive, eHierDatabase) +{ + ASSERT( mpDb != 0); + // + // make sure the address is non-null + // + util_ThrowIfNull(addr, _T("cHierDatabaseIter::LoadArrayAt")); + // + // load the info and the array + // + mInfoAddr = addr; + util_ReadObject( mpDb, &mInfo, mInfoAddr ); + cHierAddr curAddr = mInfo.mArray; + // + // load in all the array entries... + // + mEntries.clear(); + while( ! curAddr.IsNull() ) + { + mEntries.push_back( cHierEntry() ); + util_ReadObject( mpDb, &mEntries.back(), curAddr ); + curAddr = mEntries.back().mNext; + } + + // + // seek to the beginning of the array + // + SeekBegin(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// AtRoot +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::AtRoot() const //throw (eHierDatabase) +{ + bool bResult = ( mInfoAddr == mpDb->mRootArrayAddr ); + + // TODO -- maybe I want to put this in a #ifdef? + // + if( bResult ) + { + // we are at the root; assert that we have no parent... + // + ASSERT( mInfo.mParent.IsNull() ); + if( ! mInfo.mParent.IsNull() ) + { + throw eHierDatabase( _T("Root node of db has a non-null parent") ); + } + } + else + { + // if we are not at the root, assert that we have a parent... + ASSERT( ! mInfo.mParent.IsNull() ); + if( mInfo.mParent.IsNull() ) + { + throw eHierDatabase( _T("Non-root node of db has a null parent!") ); + } + } + + return bResult; +} + +/////////////////////////////////////////////////////////////////////////////// +// CanDescend +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::CanDescend() const +{ + if( Done() ) + return false; + + return (! mIter->mChild.IsNull() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Descend +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::Descend() +{ + ASSERT( CanDescend() ); + // + // alter the cwd... + // + mCurPath.Push( mIter->mName ); + + LoadArrayAt ( mIter->mChild ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Ascend +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::Ascend() +{ + ASSERT( ! AtRoot() ); + ASSERT( mCurPath.GetSize() > 0 ); + // + // alter the cwd... + // + mCurPath.Pop(); + + LoadArrayAt ( mInfo.mParent ); +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekBegin +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::SeekBegin() +{ + mIter = mEntries.begin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Done +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::Done() const +{ + return ( mIter == mEntries.end() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Next +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::Next() +{ + mIter++; +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekTo +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::SeekTo(const TCHAR* pName) +{ + EntryArray::iterator i = UpperBound( pName ); + if( i != mEntries.end() ) + { + if( 0 == Compare( pName, (*i).mName.c_str() ) ) + { + mIter = i; + return true; + } + } + + mIter = mEntries.end(); + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetName +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cHierDatabaseIter::GetName() const +{ + ASSERT( ! Done() ); + if( Done() ) + { + throw eHierDatabase( _T("Attempt to call iter::GetName() when done is true")); + } + + return mIter->mName.c_str(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetCwd +/////////////////////////////////////////////////////////////////////////////// +const TSTRING cHierDatabaseIter::GetCwd() const +{ + return mCurPath.AsString(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetCurrentAddr +/////////////////////////////////////////////////////////////////////////////// +cHierAddr cHierDatabaseIter::GetCurrentAddr() const +{ + ASSERT( ! Done() ); + if( Done() ) + { + return cHierAddr(); + } + + if( mIter == mEntries.begin() ) + { + return mInfo.mArray; + } + + return (mIter-1)->mNext; +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateChildArray +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::CreateChildArray() //throw (eArchive, eHierDatabase) +{ + ASSERT( ! Done() ); + ASSERT( ! CanDescend() ); + if( Done() ) + { + throw eHierDatabase( _T("Attempt to call iter::CreateChildArray() when done is true")); + } + if( CanDescend() ) + { + throw eHierDatabase( _T("Attempt to call iter::CreateChildArray() when child already exists")); + } + + cHierArrayInfo newInfo; + cHierAddr infoAddr; + + // write the new info + newInfo.mParent = mInfoAddr; + infoAddr = util_WriteObject( mpDb, &newInfo ); + mIter->mChild = infoAddr; + // + // rewrite the current object, since its child info just changed + // + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateEntry +// +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::CreateEntry( const TSTRING& name ) //throw (eArchive, eHierDatabase) +{ + cHierEntry newEntry; + newEntry.mName = name; + + // + // insert this in order in the set... + // + mIter = UpperBound( newEntry.mName.c_str() ); + + // + // make sure that no duplicate names are added to the database... + // + if( mIter != mEntries.end() ) + { + if( 0 == Compare( mIter->mName.c_str(), newEntry.mName.c_str() ) ) + { + return; + //throw eHierDbDupeName( name ); + } + } + + // Note -- insert() inserts directly _before_ the iterator + // we need to get the current address so we can set the new object's + // next pointer appropriately + // + cHierAddr nextAddr; + if( ! Done() ) + { + nextAddr = GetCurrentAddr(); + } + mIter = mEntries.insert( mIter, newEntry ); + // + // first, we should write the new object to the database + // + mIter->mNext = nextAddr; + cHierAddr newAddr = util_WriteObject( mpDb, &(*mIter) ); + // + // set the previous object's next pointer, and rewrite that object to disk... + // + if( mIter == mEntries.begin() ) + { + // we need to rewrite the array info... + // + mInfo.mArray = newAddr; + util_RewriteObject( mpDb, &mInfo, mInfoAddr ); + } + else + { + // altering the previous node... + // + mIter--; + mIter->mNext = newAddr; + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); + mIter++; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// GetData +/////////////////////////////////////////////////////////////////////////////// +int8* cHierDatabaseIter::GetData(int32& length) const //throw (eArchive, eHierDatabase) +{ + ASSERT( HasData() ); + if( ! HasData() ) + { + throw eHierDatabase( _T("Attempt to get data from a node when HasData() is false")); + } + + // + // note that we can only get data for reading; perhaps in the future I will add + // support for retrieving data for writing as well. + // + return mpDb->GetDataForReading( cBlockRecordFile::tAddr(mIter->mData.mBlockNum, mIter->mData.mIndex), length ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// HasData +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::HasData() const +{ + ASSERT( ! Done() ); + if( Done() ) + return false; + + return ( ! mIter->mData.IsNull() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// SetData +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::SetData(int8* pData, int32 length) //throw (eArchive, eHierDatabase) +{ + ASSERT( ! Done() ); + ASSERT( ! HasData() ); + + // remove the item's data, if there is any... + // + if( HasData() ) + { + RemoveData(); + } + // + // add the data and set the entry's data pointer appropriately + // + cBlockRecordFile::tAddr addr = mpDb->AddItem( pData, length ); + mIter->mData = cHierAddr( addr.mBlockNum, addr.mIndex ); + // + // update the entry on disk... + // + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveData +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::RemoveData() //throw (eArchive, eHierDatabase) +{ + ASSERT( ! Done() ); + if( ! HasData() ) + { + ASSERT( false ); + return; + } + + mpDb->RemoveItem( cBlockRecordFile::tAddr( mIter->mData.mBlockNum, mIter->mData.mIndex ) ); + // + // now, we need to update the node's data pointer and save the node to disk + // + mIter->mData = cHierAddr(); + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// DeleteEntry +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::DeleteEntry() //throw (eArchive, eHierDatabase) +{ + ASSERT( ! Done() ); + ASSERT( ! CanDescend() ); // this node can't have any children. + cDebug d("cHierDatabaseIter::DeleteEntry"); + + if( Done() ) + { + d.TraceDetail("Attempt to DeleteEntry() when Done() == true; returning\n"); + return; + } + if( CanDescend() ) + { + throw eHierDatabase( _T("Attempt to delete an entry that still has children.\n")); + } + + // + // first, we should set the previous node's next pointer... + // + cHierAddr curAddr = GetCurrentAddr(); + if( mIter == mEntries.begin() ) + { + // we are changing the info's mArray pointer + // + mInfo.mArray = mIter->mNext; + util_RewriteObject( mpDb, &mInfo, mInfoAddr ); + } + else + { + // altering the previous node... + // + mIter--; + mIter->mNext = (mIter+1)->mNext; + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); + mIter++; + } + // + // now, delete the node from the file and from our array... + // + mpDb->RemoveItem( cBlockRecordFile::tAddr( curAddr.mBlockNum, curAddr.mIndex ) ); + mIter = mEntries.erase(mIter); + +} + +/////////////////////////////////////////////////////////////////////////////// +// CanDeleteChildArray +/////////////////////////////////////////////////////////////////////////////// +bool cHierDatabaseIter::ChildArrayEmpty() +{ + ASSERT( ! Done() ); + ASSERT( CanDescend() ); + + cHierArrayInfo info; + util_ReadObject ( mpDb, &info, mIter->mChild ); + return ( info.mArray.IsNull() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// DeleteChildArray +/////////////////////////////////////////////////////////////////////////////// +void cHierDatabaseIter::DeleteChildArray() //throw (eArchive, eHierDatabase) +{ + ASSERT( ! Done() ); + ASSERT( CanDescend() ); + cDebug d("cHierDatabaseIter::DeleteChildArray"); + + if( Done() ) + { + d.TraceDetail("Attempt to DeleteChildArray() when Done() == true; returning\n"); + return; + } + if( ! CanDescend() ) + { + d.TraceDetail("Attempt to DeleteChildArray() when none exists; returning\n"); + return; + } + // + // make sure that the child index is empty... + // + if( ! ChildArrayEmpty() ) + { + ASSERT( false ); + throw eHierDatabase( _T("Attempt to delete a child array that still has entries") ); + } + // + // ok, no we can remove it... + // + mpDb->RemoveItem( cBlockRecordFile::tAddr( mIter->mChild.mBlockNum, mIter->mChild.mIndex ) ); + mIter->mChild = cHierAddr(); + util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// CompareForUpperBound +/////////////////////////////////////////////////////////////////////////////// + +bool cHierDatabaseIter::CompareForUpperBound( const cHierEntry& he, const TCHAR* pchName ) const +{ + return( 0 > Compare( he.mName.c_str(), pchName ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// cHierDatabaseIterCallCompare +// -- used to sneak a pointer-to-member-function where a +// pointer-to-non-member-function is expected +/////////////////////////////////////////////////////////////////////////////// +class cHierDatabaseIterCallCompare +{ +public: + cHierDatabaseIterCallCompare( const cHierDatabaseIter* pcls ) + : pc( pcls ) {}; + + bool operator()( const cHierEntry& a1, const TCHAR* a2 ) + { + return pc->CompareForUpperBound( a1, a2 ); + } + +private: + const cHierDatabaseIter* pc; +}; + +/////////////////////////////////////////////////////////////////////////////// +// UpperBound +/////////////////////////////////////////////////////////////////////////////// + +cHierDatabaseIter::EntryArray::iterator cHierDatabaseIter::UpperBound( const TCHAR* pchName ) +{ + cHierDatabaseIterCallCompare comp( this ); + return ::UpperBound( mEntries.begin(), mEntries.end(), pchName, comp ); +} + + diff --git a/src/db/hierdatabase.h b/src/db/hierdatabase.h new file mode 100644 index 0000000..aad63dd --- /dev/null +++ b/src/db/hierdatabase.h @@ -0,0 +1,280 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// hierdatabase.h +// +#ifndef __HIERDATABASE_H +#define __HIERDATABASE_H + +#ifndef __BLOCKRECORDFILE_H +#include "blockrecordfile.h" +#endif +#ifndef __HIERDBNODE_H +#include "hierdbnode.h" +#endif +#ifndef __ERROR_H +#include "core/error.h" +#endif + +#ifndef __HIERDBPATH_H +#include "hierdbpath.h" +#endif + +class cHierDatabaseIter; +class cErrorBucket; + + +TSS_EXCEPTION( eHierDatabase, eError ); +TSS_EXCEPTION( eHierDbInternal, eHierDatabase ); // not used +TSS_EXCEPTION( eHierDbDupeName, eHierDatabase ); + +// +// TODO -- store some header info with the root node -- at least whether the db is case-sensitive or not +// and what the delimiting character is +// + +//----------------------------------------------------------------------------- +// cHierDatabase -- a hierarchical database class +//----------------------------------------------------------------------------- +class cHierDatabase : public cBlockRecordFile +{ +public: + cHierDatabase( bool bCaseSensitive = true, TCHAR delChar = _T('/') ); + // NOTE -- these two parameters are only used if the database is being created; otherwise, they + // are overwritten when Open() is called. + virtual ~cHierDatabase(); + + // + // overrides from base class + // + virtual void Open ( const TSTRING& fileName, int numPages = 5, bool bTruncate = false ); //throw (eArchive, eHierDatabase) + virtual void Open ( cBidirArchive* pArch, int numPages = 5 ); //throw (eArchive, eHierDatabase) + // for the second Open(), this class owns the destruction of the archive + //TODO -- make numPages the last parameter + + bool IsCaseSensitive() const { return mbCaseSensitive; } + TCHAR GetDelimitingChar() const { return mDelimitingChar; } + + enum { INVALID_INDEX = -1 }; + + typedef cHierDatabaseIter iterator; + typedef cBlockRecordFile inherited; +private: + cHierAddr mRootArrayAddr; // this is the address of the top-level array + bool mbCaseSensitive; + TCHAR mDelimitingChar; + + cHierDatabase ( const cHierDatabase& rhs ); //not impl + void operator= ( const cHierDatabase& rhs ); //not impl + + void OpenImpl ( bool bTruncate ); //throw (eArchive, eHierDatabase) + // both Open() methods call this to initialize the class after calling + // inherited::Open() + + friend class cHierDatabaseIter; +}; + +//----------------------------------------------------------------------------- +// cHierDatabaseIter -- the iterator class +//----------------------------------------------------------------------------- +class cHierDatabaseIter +{ +public: + cHierDatabaseIter( cHierDatabase* pDb ); //throw (eArchive) + ~cHierDatabaseIter(); + + // + // copying + // + cHierDatabaseIter ( const cHierDatabaseIter& rhs ); + cHierDatabaseIter& operator=( const cHierDatabaseIter& rhs ); + + // + // name characteristics -- these are alternatives to specifying in the ctor + // + void SetCaseSensitive ( bool bCaseSensitive ); + bool IsCaseSensitive ( void ) const; + void SetDelimitingChar ( TCHAR c ); + TCHAR GetDelimitingChar ( void ) const; + + // + // traverse up and down the hierarchy + // + bool AtRoot() const; //throw (eHierDatabase) + bool CanDescend() const; + void Descend() ; + void Ascend() ; + // + // traverse my peers (objects in the same directory as me) + // + void SeekBegin(); + bool Done() const; + void Next(); + bool SeekTo(const TCHAR* pName); + // seeks to the named peer; returns false and is positioned in an undefined + // place if it can't find the peer. + // it is either case sensitive or insensitive, depending on what was passed to the + // ctor. + void SeekToRoot(); //throw (eArchive) + // positions the iterator at the root node + + void Refresh(); //throw (eArchive, eHierDatabase) + // refresh the iterator's contents in case the db has changed since we first entered + // this directory. + // note that this will move the iterator back to the beginning of the array + + // + // getting at the entry's data... + // + const TCHAR* GetName() const; + const TSTRING GetCwd() const; + // + // creating arrays and entries (ie directories and files) + // + void CreateChildArray(); //throw (eArchive, eHierDatabase) + void CreateEntry ( const TSTRING& name );//throw (eArchive, eHierDatabase) + // after the entry is added, this iterator points at it. + // if the entry already exists in the database, an error is added to pError. + + // + // getting and setting the data associated with a given entry + // + int8* GetData(int32& length) const; //throw (eArchive, eHierDatabase) + // returns the data associated with the current entry; this asserts that the iterator is + // not done and the current entry has data associated with it + bool HasData() const ; + // returns true if the current entry has data + void SetData(int8* pData, int32 length); //throw (eArchive, eHierDatabase) + void RemoveData(); //throw (eArchive, eHierDatabase) + // removes the data associated with the current entry; this asserts that the current + // entry actually _has_ data + // + // deleting arrays and entries + // + void DeleteEntry(); //throw (eArchive, eHierDatabase) + // deletes the currently pointed-at entry; this assumes that Done() is not true, and + // advances to the next node. + bool ChildArrayEmpty(); //throw (eArchive, eHierDatabase) + // returns true if the node's child array is empty + void DeleteChildArray(); //throw (eArchive, eHierDatabase) + // this method deletes the child array of the current object. This method asserts that + // Done() is not true, that the current node has a child, and that the child array is + + // empty (TODO -- perhaps in the future we will want to make the equivalant of "rm -rf" + + // + // util function for sorting/searching + // + bool CompareForUpperBound( const cHierEntry& he, const TCHAR* pchName ) const; + // compares shortname of FCO to pchName. returns < == or > 0 as strcmp does. + +protected: + + cHierAddr GetCurrentAddr() const; + // returns the address of the current cHierEntry by examining either the previous pNext pointer or the + // array info pointer if the first entry is current. This asserts (! Done()) + + //------------------------------------------------------------------------- + // member data + //------------------------------------------------------------------------- + // TODO -- maybe this should be a fully insulated class? + // TODO -- maybe this should be a set to reduce insert and lookup time? + typedef std::vector EntryArray; + + + cHierDatabase* mpDb; // the database + EntryArray mEntries; // vector of entries for the current level + cHierArrayInfo mInfo; + cHierAddr mInfoAddr; + EntryArray::iterator mIter; // my current position in the array + cHierDbPath mCurPath; // The current working directory. + + //------------------------------------------------------------------------- + // helper methods + //------------------------------------------------------------------------- + void LoadArrayAt(const cHierAddr& addr); //throw (eArchive, eHierDatabase) + // initializes the iterator so that it is pointing at the array named by addr. + int Compare( const TCHAR* pc1, const TCHAR* pc2 ) const; + // this acts just like strcmp, but takes into account whether the database is case-sensitive or not. + + EntryArray::iterator UpperBound( const TCHAR* pchName ); + // same as std::upper_bound except it calls CompareForUpperBound() to + // do its comparison. +}; + +//############################################################################# +// inline implementation +//############################################################################# +inline void cHierDatabaseIter::Refresh() +{ + cHierAddr infoAddr = mInfoAddr; + LoadArrayAt( infoAddr ); +} + +inline void cHierDatabaseIter::SetCaseSensitive ( bool bCaseSensitive ) +{ + mCurPath.SetCaseSensitive( bCaseSensitive ); +} + +inline bool cHierDatabaseIter::IsCaseSensitive( void ) const +{ + return mCurPath.IsCaseSensitive(); +} + +inline void cHierDatabaseIter::SetDelimitingChar( TCHAR c ) +{ + mCurPath.SetDelimiter( c ); +} + +inline TCHAR cHierDatabaseIter::GetDelimitingChar( void ) const +{ + return mCurPath.GetDelimiter(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Compare +/////////////////////////////////////////////////////////////////////////////// +inline int cHierDatabaseIter::Compare( const TCHAR* pc1, const TCHAR* pc2 ) const +{ + if( mCurPath.IsCaseSensitive() ) + { + return ( _tcscmp( pc1, pc2 ) ); + } + else + { + return ( _tcsicmp( pc1, pc2 ) ); + } +} + + +#endif //__HIERDATABASE_H + diff --git a/src/db/hierdatabase_t.cpp b/src/db/hierdatabase_t.cpp new file mode 100644 index 0000000..bd3401c --- /dev/null +++ b/src/db/hierdatabase_t.cpp @@ -0,0 +1,350 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// hierdatabase_t +#include "stddb.h" +#include "hierdatabase.h" +#include "test/test.h" +#include "core/error.h" + +static void PrintDb( cHierDatabase::iterator iter, cDebug d, bool bFirst = true ) +{ + if( ! bFirst ) + { + iter.Descend(); + } + d.TraceDebug( "-- Processing directory %s\n", iter.GetCwd().c_str() ); + + for( iter.SeekBegin(); ! iter.Done(); iter.Next() ) + { + d.TraceDebug( "Processing entry %s\n", iter.GetName() ); + if( iter.CanDescend() ) + { + d.TraceDebug( ">>Descending...\n" ); + PrintDb(iter, d, false); + } + } + + d.TraceDebug( "-- Done Processing directory %s\n", iter.GetCwd().c_str() ); +} + +static void GetNoun( TSTRING& noun ) +{ + static TSTRING prevNoun; + TCIN >> noun; + if( noun.compare( _T("!$") ) == 0 ) + { + noun = prevNoun; + } + prevNoun = noun; +} + +/////////////////////////////////////////////////////////////////////////////// +// TestHierDatabaseInteractive -- this provides an interactive interface to +// the database +/////////////////////////////////////////////////////////////////////////////// +void TestHierDatabaseInteractive() +{ + cDebug d( "TestHierDatabaseInteractive" ); + try + { + cHierDatabase db; + //db.Open( _T("c:/tmp/tw.hdb"), 5, true); + db.Open( _T("c:/tmp/tw.db"), 5, false); + cHierDatabase::iterator iter(&db); + + while( true ) + { + TSTRING verb, noun; + TCOUT << _T(">>"); + TCIN >> verb; + // + // ok, now we switch on the command... + // + //----------------------------------------------------------------- + // quit + //----------------------------------------------------------------- + if( verb.compare( _T("quit") ) == 0 ) + { + // the quit command... + break; + } + //----------------------------------------------------------------- + // print + //----------------------------------------------------------------- + if( verb.compare( _T("print") ) == 0 ) + { + // the print command... + ASSERT( false ); + // TODO -- Implement this! + } + //----------------------------------------------------------------- + // mkdir + //----------------------------------------------------------------- + else if( verb.compare( _T("mkdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making a child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + iter.CreateChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // mk + //----------------------------------------------------------------- + else if( verb.compare( _T("mk") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + TCOUT << "Error: object already exists!" << std::endl; + } + else + { + iter.CreateEntry( noun ); + } + } + //----------------------------------------------------------------- + // rmdir + //----------------------------------------------------------------- + else if( verb.compare( _T("rmdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing the child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + //TODO -- check that it has an empty child + iter.DeleteChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // rm + //----------------------------------------------------------------- + else if( verb.compare( _T("rm") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Can't delete object; it still has children." << std::endl; + } + else + { + iter.DeleteEntry(); + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwd + //----------------------------------------------------------------- + else if( verb.compare( _T("pwd") ) == 0 ) + { + TCOUT << iter.GetCwd() << std::endl; + } + //----------------------------------------------------------------- + // ls + //----------------------------------------------------------------- + else if( verb.compare( _T("ls") ) == 0 ) + { + int cnt = 0; + for( iter.SeekBegin(); ! iter.Done(); iter.Next(), cnt++ ) + { + TCOUT << "[" << cnt ; + if( iter.CanDescend() ) + { + TCOUT << "]*\t" ; + } + else + { + TCOUT << "]\t" ; + } + TCOUT << iter.GetName() << std::endl; + } + } + //----------------------------------------------------------------- + // cd + //----------------------------------------------------------------- + else if( verb.compare( _T("cd") ) == 0 ) + { + GetNoun(noun); + if( noun.compare( _T("..") ) == 0 ) + { + if( iter.AtRoot() ) + { + TCOUT << "Can't ascend above root." << std::endl; + } + else + { + TCOUT << "Ascending..." << std::endl; + iter.Ascend(); + } + } + else + { + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Descending into " << noun << std::endl; + iter.Descend(); + } + else + { + TCOUT << noun << " has no children; can't descend." << std::endl; + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + } + //----------------------------------------------------------------- + // rmdir + //----------------------------------------------------------------- + else if( verb.compare( _T("rmdir") ) == 0 ) + { + GetNoun(noun); + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Deleting child of " << iter.GetName() << std::endl; + iter.DeleteChildArray(); + } + else + { + TCOUT << noun << " has no child; can't delete." << std::endl; + } + } + + } + //----------------------------------------------------------------- + // rm + //----------------------------------------------------------------- + else if( verb.compare( _T("rm") ) == 0 ) + { + GetNoun(noun); + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << noun << " doesn't exist; can't delete." << std::endl; + } + else + { + TCOUT << "Deleting " << iter.GetName() << std::endl; + iter.DeleteEntry(); + } + } + + } + //----------------------------------------------------------------- + // set + //----------------------------------------------------------------- + else if( verb.compare( _T("set") ) == 0 ) + { + GetNoun(noun); + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.HasData() ) + { + iter.RemoveData(); + } + TSTRING data; + TCIN >> data; + iter.SetData( (int8*)data.c_str(), data.length() + 1 ); + TCOUT << "Setting " << noun << "'s data to " << data << std::endl; + } + else + { + TCOUT << "Can't find object " << noun << std::endl; + } + + } + //----------------------------------------------------------------- + // get + //----------------------------------------------------------------- + else if( verb.compare( _T("get") ) == 0 ) + { + GetNoun(noun); + if( iter.SeekTo( noun.c_str() ) ) + { + if( ! iter.HasData() ) + { + TCOUT << "Object has no data!" << std::endl; + } + else + { + int32 dummyLength; + TCOUT << noun << "'s data is: " << (TCHAR*)iter.GetData(dummyLength) << std::endl; + } + } + else + { + TCOUT << "Can't find object " << noun << std::endl; + } + + } + + // make sure the file is still valid... + // +#ifdef _BLOCKFILE_DEBUG + db.AssertAllBlocksValid() ; +#endif + } + + TCOUT << "Exiting..." << std::endl; + + } + catch( eError& e ) + { + d.TraceError( "Exception caught: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + TEST( false ); + } + +} diff --git a/src/db/hierdbnode.h b/src/db/hierdbnode.h new file mode 100644 index 0000000..51636d4 --- /dev/null +++ b/src/db/hierdbnode.h @@ -0,0 +1,288 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// hierdbnode.h +// +// these classes are used by cHierDatabase as the nodes in the hierarchy +// +#ifndef __HIERDBNODE_H +#define __HIERDBNODE_H + +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __ARCHIVE_H +#include "archive.h" +#endif + +/////////////////////////// +// BIG TODO -- I need to change all of these strings to be wchar_t instead of TSTRINGS +// Also, they should serialize themselves in a platform-neutral byte order +/////////////////////////// + +//----------------------------------------------------------------------------- +// cHierNode -- the base class for all other nodes; this class contains type +// information +//----------------------------------------------------------------------------- +class cHierNode +{ +public: + enum Type + { + TYPE_INVALID = -1, + TYPE_MIN = 0, + TYPE_ROOT = 1, + TYPE_ENTRY, + TYPE_ARRAY, + TYPE_ARRAY_INFO, + TYPE_MAX + }; + + + cHierNode( Type type = TYPE_INVALID ) : mType( type ) {} + virtual ~cHierNode() {} + + int32 mType; + + ///////////////////////////////////////// + // methods to override + ///////////////////////////////////////// + virtual int32 CalcArchiveSize() const { return ( sizeof(mType) ); } + // this method should return the amount of space that this class will take up in an archive + // derived classes should override this if they have any data members that will be stored + // with Read() or Write() + virtual void Write ( cArchive& arch ) const //throw(eArchive) + { arch.WriteInt32( mType ); } + virtual void Read ( cArchive& arch ) //throw(eArchive) + { + arch.ReadInt32( mType ); + // + // do a rudimentary integrity check... + // + if( (mType <= TYPE_MIN) || (mType >= TYPE_MAX) ) + { + ASSERT( false ); + throw eArchiveFormat( _T("Invalid type encountered in cHierNode::Read") ); + } + + } + // these methods read and write the class to an archive. We had better be sure that + // we don't write more than we said we would in CalcArchiveSize() ! +}; + +//----------------------------------------------------------------------------- +// cHierAddr -- the "address" of different items in the hierarchy +//----------------------------------------------------------------------------- +class cHierAddr +{ +public: + int32 mBlockNum; + int32 mIndex; + + cHierAddr( int32 block = -1, int32 index = -1 ) : mBlockNum( block ), mIndex( index ) {} + + bool IsNull() const { return (mBlockNum == -1); } + // returns true if the address points to "null" (ie -- no valid address) + bool operator==( const cHierAddr& rhs ) const { return( (mBlockNum == rhs.mBlockNum) && (mIndex == rhs.mIndex) ); } + + + ///////////////////////////////////////////////// + // serialization methods + ///////////////////////////////////////////////// + int32 CalcArchiveSize () const + { + return ( sizeof(mBlockNum) + sizeof(mIndex) ); + } + void Write( cArchive& arch ) const //throw(eArchive) + { + arch.WriteInt32( mBlockNum ); + arch.WriteInt32( mIndex ); + } + void Read( cArchive& arch ) //throw(eArchive) + { + arch.ReadInt32 ( mBlockNum ); + arch.ReadInt32 ( mIndex ); + } + +}; + + +//----------------------------------------------------------------------------- +// cHierRoot -- the root of the hierarchy; you can always count on this being +// at (0, 0) +//----------------------------------------------------------------------------- +class cHierRoot : public cHierNode +{ +public: + cHierRoot() : cHierNode( TYPE_ROOT ) {} + + cHierAddr mChild; // points to a cHierArray or an invalid address + bool mbCaseSensitive; // determines the case-sensitiveness of lookups, ordering, etc. + TCHAR mDelimitingChar; // the delimiting character; this is used when displaying a path to the user + + ///////////////////////////////////////////////// + // serialization methods + ///////////////////////////////////////////////// + virtual int32 CalcArchiveSize() const + { + return ( cHierNode::CalcArchiveSize() + mChild.CalcArchiveSize() ); + } + virtual void Write ( cArchive& arch ) const //throw(eArchive) + { + cHierNode::Write ( arch ); + mChild.Write ( arch ); + arch.WriteInt32 ( mbCaseSensitive ? 1 : 0 ); + TSTRING dc ( &mDelimitingChar, 1 ); + arch.WriteString ( dc ); + } + virtual void Read ( cArchive& arch ) //throw(eArchive) + { + cHierNode::Read ( arch ); + // + // make sure the type is correct + // + if( mType != TYPE_ROOT ) + { + ASSERT( false ); + throw eArchiveFormat( _T("Invalid type encountered; expected ROOT node") ); + } + mChild.Read ( arch ); + int32 cs; + arch.ReadInt32 ( cs ); + mbCaseSensitive = cs ? true : false; + TSTRING dc; + arch.ReadString ( dc ); + if( dc.length() != 1 ) + { + ASSERT( false ); + throw eArchiveFormat( _T("Read of the root node failed; invalid delimiting character.") ); + } + mDelimitingChar = dc[0]; + } +}; + +//----------------------------------------------------------------------------- +// cHierEntry -- an entry that contains a name and points to some data +//----------------------------------------------------------------------------- +class cHierEntry : public cHierNode +{ +public: + cHierEntry() : cHierNode( TYPE_ENTRY ) {} + + TSTRING mName; // TODO -- change this to a wchar_t string + cHierAddr mData; + cHierAddr mChild; // points to a cHierArray or an invalid address + cHierAddr mNext; // the next peer entry in the linked list, or Null() if done + + ///////////////////////////////////////////////// + // serialization methods + ///////////////////////////////////////////////// + virtual int32 CalcArchiveSize() const + { + return ( cHierNode::CalcArchiveSize() + mChild.CalcArchiveSize() + + mData.CalcArchiveSize() + cArchive::GetStorageSize( mName ) + + mNext.CalcArchiveSize() ); + } + virtual void Write ( cArchive& arch ) const //throw(eArchive) + { + cHierNode::Write( arch ); + arch.WriteString( mName ); + mChild.Write ( arch ); + mData.Write ( arch ); + mNext.Write ( arch ); + } + virtual void Read ( cArchive& arch ) //throw(eArchive) + { + cHierNode::Read ( arch ); + // + // make sure the type is correct + // + if( mType != TYPE_ENTRY ) + { + ASSERT( false ); + throw eArchiveFormat( _T("Invalid type encountered; expected ENTRY node") ); + } + + arch.ReadString ( mName ); + mChild.Read ( arch ); + mData.Read ( arch ); + mNext.Read ( arch ); + } + +}; + +//----------------------------------------------------------------------------- +// cHierArrayInfo -- constant-size struct that contains information about an array +//----------------------------------------------------------------------------- +class cHierArrayInfo : public cHierNode +{ +public: + cHierArrayInfo() : cHierNode( TYPE_ARRAY_INFO ) {} + + cHierAddr mParent; // points to a cHierArrayInfo or cHierRoot + cHierAddr mArray; // points to cHierEntryArray + + ///////////////////////////////////////////////// + // serialization methods + ///////////////////////////////////////////////// + virtual int32 CalcArchiveSize() const + { + return (cHierNode::CalcArchiveSize() + mParent.CalcArchiveSize() + mArray.CalcArchiveSize()); + } + virtual void Write ( cArchive& arch ) const //throw(eArchive) + { + cHierNode::Write( arch ); + mParent.Write ( arch ); + mArray.Write ( arch ); + } + virtual void Read ( cArchive& arch ) //throw(eArchive) + { + cHierNode::Read ( arch ); + // + // make sure the type is correct + // + if( mType != TYPE_ARRAY_INFO ) + { + ASSERT( false ); + throw eArchiveFormat( _T("Invalid type encountered; expected TYPE_ARRAY_INFO node") ); + } + + mParent.Read ( arch ); + mArray.Read ( arch ); + } + +}; + + + +#endif //__HIERDBNODE_H + diff --git a/src/db/hierdbpath.cpp b/src/db/hierdbpath.cpp new file mode 100644 index 0000000..ff21ebb --- /dev/null +++ b/src/db/hierdbpath.cpp @@ -0,0 +1,179 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// hierdbpath.cpp : Implements cHierDbPath. +// + +#include "stddb.h" + +#include "hierdbpath.h" +#include "core/debug.h" + +//Ctor: +cHierDbPath::cHierDbPath( void ) : + mbCaseSensitive(false), mDelimitingChar( _T('/') ) +{ + ASSERT( mCurrPath.empty() ); +} + +cHierDbPath::cHierDbPath( TCHAR cDelChar, bool bCaseSensitive ) : + mbCaseSensitive( bCaseSensitive ), mDelimitingChar( cDelChar ) +{ + ASSERT( mCurrPath.empty() ); +} + +//Copy Ctor: +cHierDbPath::cHierDbPath( const cHierDbPath& rhs ) +{ + mbCaseSensitive = rhs.mbCaseSensitive; + mDelimitingChar = rhs.mDelimitingChar; + + if( !rhs.mCurrPath.empty() ) + { + DbPath::const_iterator it = rhs.mCurrPath.begin(); + for( ; it != rhs.mCurrPath.end(); ++it ) + mCurrPath.push_back( *it ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +cHierDbPath& cHierDbPath::operator=( const cHierDbPath& rhs ) +{ + if (this != &rhs) + { + mbCaseSensitive = rhs.mbCaseSensitive; + mDelimitingChar = rhs.mDelimitingChar; + + if( !rhs.mCurrPath.empty() ) + { + DbPath::const_iterator it = rhs.mCurrPath.begin(); + for( ; it != (rhs.mCurrPath.end()); ++it ) + mCurrPath.push_back( *it ); + } + } + return *this; +} + +//Dtor: +cHierDbPath::~cHierDbPath( void ) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Push: Adds a substring to the end of the sequence(path) +void cHierDbPath::Push( const TSTRING &str ) +{ + mCurrPath.push_back( str ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Pop: Removes a substring from the end of the path and returns it as a +// TSTRING. +TSTRING cHierDbPath::Pop( void ) +{ + TSTRING ret; + + if ( mCurrPath.empty() ) + return _T(""); + + ret = mCurrPath.back(); + + mCurrPath.pop_back(); + + return ret; +} + +void cHierDbPath::SetCaseSensitive( bool bCaseSensitive ) +{ + mbCaseSensitive = bCaseSensitive; +} + +bool cHierDbPath::IsCaseSensitive( void ) const +{ + return mbCaseSensitive; +} + +void cHierDbPath::SetDelimiter( TCHAR Delimiter ) +{ + mDelimitingChar = Delimiter; +} + +TCHAR cHierDbPath::GetDelimiter( void ) const +{ + return mDelimitingChar; +} + +void cHierDbPath::Clear( void ) +{ + mCurrPath.clear(); + + ASSERT( mCurrPath.empty() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AsString -- Returns a TSTRING representation of the current path +TSTRING cHierDbPath::AsString( void ) const +{ + TSTRING ret = _T(""); + + if(mCurrPath.size() == 1) + { + ret = *(mCurrPath.begin()); + ret += mDelimitingChar; + return ret; + } + + DbPath::const_iterator it = mCurrPath.begin(); + + // The loop adds delimiting characters until the last element in the + // sequence is reached, so we don't have a trailing character. + while(it != mCurrPath.end() ) + { + // the loop is constructed in this odd fashion because I don't want a trailing mDelimiter + ret += (*it); + ++it; + if(it != mCurrPath.end()) + ret += mDelimitingChar; + } + + //return the completed TSTRING + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSize: Returns the number of substrings in the sequence +int cHierDbPath::GetSize( void ) const +{ + return mCurrPath.size(); +} + diff --git a/src/db/hierdbpath.h b/src/db/hierdbpath.h new file mode 100644 index 0000000..75f86b6 --- /dev/null +++ b/src/db/hierdbpath.h @@ -0,0 +1,95 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// hierdbpath.h : +// + +#ifndef __HIERDBPATH_H +#define __HIERDBPATH_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#include + +/////////////////////////////////////////////////////////////////////////////// +// cHierDbPath: +// A class for maintaining a pathname object that can be added to and +// removed from using push and pop operations. A toggling of case- +// sensitivitity/insensitivity is also supplied, as well as the ability +// to set/change the delimiting character in the path. +class cHierDbPath +{ +public: + // Ctor, Dtor: + cHierDbPath(); //empty constructor: + // Default delimiter = '/', default case-sensitivity = false + + cHierDbPath( TCHAR delChar, bool bCaseSensitive ); + ~cHierDbPath(); + + // Copy Ctor: + cHierDbPath ( const cHierDbPath& rhs ); + + cHierDbPath& operator=( const cHierDbPath& rhs ); + + void SetDelimiter ( TCHAR cDelimiter ); + TCHAR GetDelimiter ( void ) const; + void SetCaseSensitive ( bool bCaseSensitive ); + bool IsCaseSensitive ( void ) const; + + void Clear ( void ); + void Push ( const TSTRING& str ); + // Pushes a substring onto the end of the path( using str ); + TSTRING Pop ( void ); + // Pops a substring off of the end of the path, and returns it. + // mCurrPath is altered by removing the substring. + + TSTRING AsString ( void ) const; + // Returns a TSTRING representation of mCurrPath. + + int GetSize ( void ) const; + // Returns the number of substrings in the path. + + typedef std::vector DbPath; +private: + + bool mbCaseSensitive; + TCHAR mDelimitingChar; + + DbPath mCurrPath; + // Data structure for holding the path. +}; + +#endif //__HIERDBPATH_H + diff --git a/src/db/stddb.cpp b/src/db/stddb.cpp new file mode 100644 index 0000000..22bd5cc --- /dev/null +++ b/src/db/stddb.cpp @@ -0,0 +1,41 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stddb.cpp +// Date....: 05/11/99 +// Creator.: rdifalco +// +// + +#include "stddb.h" + +// eof: stddb.cpp diff --git a/src/db/stddb.h b/src/db/stddb.h new file mode 100644 index 0000000..301ed7a --- /dev/null +++ b/src/db/stddb.h @@ -0,0 +1,45 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stddb.h +// Date....: 05/07/99 +// Creator.: +// +// + +#ifndef __STDDB_H +#define __STDDB_H + +#include "core/stdcore.h" + +#endif //__STDDB_H + diff --git a/src/dep_addprefix.pl b/src/dep_addprefix.pl new file mode 100755 index 0000000..d751f9a --- /dev/null +++ b/src/dep_addprefix.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl -w + +# include a null char so VSS treats this as a binary file --> " #" + +##################################################################### +# dep_addprefix.pl +# +# Usage: dep_addprefix.pl myproject.mak.dep objdir1 [objdir2 ...] +# +# Modifies a "make depends" file so that it supports the generation of +# object files in subdirs. +# +# For example if our source file is foo.cpp and we want to have +# the release and debug objects live different directories we would +# run: +# +# dep_addprefix.pl Makefile.dep release debug +# +# This would take the instances of +# +# foo.o: dependantcy.h +# +# and change them to +# +# release/foo.o: dependancy.h +# debug/foo.o: dependancy.h +# +# +# ### May 2nd, 2000 - dmb +# +# Added the ability to cope with g++ -M output, which uses the "\" character +# to continue long lines. As a first step we turn multiple lines ending with +# "\" to a single line in order to cope with this. +# + +if (!defined($ARGV[0]) || !defined($ARGV[1])) +{ + print <)) +{ + # the following if/else logic concatinates lines that end with the "\" character + if ($instring =~ /.*\\$/) + { + $instring =~ s/(.*)\\$/$1/; + $process_string .= substr($instring, 0, -1); # use substr(,,-1) to avoid eol character + } + else + { + $process_string .= $instring; + + if ($process_string =~ /^.*:.*$/) + { + foreach $objdir (@objdir_list) + { + $text .= $objdir . $process_string; + } + } + else + { + $text .= $process_string; + } + + $process_string = ""; + } +} + +close(IN); + +open (OUT, ">$dep_file") || die "Can't open $dep_file for writing.\n"; +print OUT $text; +close (OUT); + +exit(0); +__END__ + diff --git a/src/fco/Makefile.am b/src/fco/Makefile.am new file mode 100644 index 0000000..f4c498d --- /dev/null +++ b/src/fco/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libfco.a +libfco_a_SOURCES = \ + fco.cpp fcocompare.cpp fcodatasourceiter.cpp \ + fcodatasourceiterimpl.cpp fcoerrors.cpp fconame.cpp \ + fconametbl.cpp fcopropimpl.cpp fcopropvector.cpp \ + fcosetimpl.cpp fcospec.cpp fcospecattr.cpp fcospechelper.cpp \ + fcospecimpl.cpp fcospeclist.cpp fcospecutil.cpp fcostrings.cpp \ + fcoundefprop.cpp genreinfo.cpp genrespeclist.cpp \ + genreswitcher.cpp signature.cpp stdfco.cpp twfactory.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libfco_a_OBJECTS) diff --git a/src/fco/Makefile.in b/src/fco/Makefile.in new file mode 100644 index 0000000..c11adb5 --- /dev/null +++ b/src/fco/Makefile.in @@ -0,0 +1,412 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libfco_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/fco +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libfco_a_AR = $(AR) $(ARFLAGS) +libfco_a_LIBADD = +am_libfco_a_OBJECTS = fco.$(OBJEXT) fcocompare.$(OBJEXT) \ + fcodatasourceiter.$(OBJEXT) fcodatasourceiterimpl.$(OBJEXT) \ + fcoerrors.$(OBJEXT) fconame.$(OBJEXT) fconametbl.$(OBJEXT) \ + fcopropimpl.$(OBJEXT) fcopropvector.$(OBJEXT) \ + fcosetimpl.$(OBJEXT) fcospec.$(OBJEXT) fcospecattr.$(OBJEXT) \ + fcospechelper.$(OBJEXT) fcospecimpl.$(OBJEXT) \ + fcospeclist.$(OBJEXT) fcospecutil.$(OBJEXT) \ + fcostrings.$(OBJEXT) fcoundefprop.$(OBJEXT) \ + genreinfo.$(OBJEXT) genrespeclist.$(OBJEXT) \ + genreswitcher.$(OBJEXT) signature.$(OBJEXT) stdfco.$(OBJEXT) \ + twfactory.$(OBJEXT) +libfco_a_OBJECTS = $(am_libfco_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libfco_a_SOURCES) +DIST_SOURCES = $(libfco_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ -fpermissive +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libfco.a +libfco_a_SOURCES = \ + fco.cpp fcocompare.cpp fcodatasourceiter.cpp \ + fcodatasourceiterimpl.cpp fcoerrors.cpp fconame.cpp \ + fconametbl.cpp fcopropimpl.cpp fcopropvector.cpp \ + fcosetimpl.cpp fcospec.cpp fcospecattr.cpp fcospechelper.cpp \ + fcospecimpl.cpp fcospeclist.cpp fcospecutil.cpp fcostrings.cpp \ + fcoundefprop.cpp genreinfo.cpp genrespeclist.cpp \ + genreswitcher.cpp signature.cpp stdfco.cpp twfactory.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/fco/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/fco/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libfco.a: $(libfco_a_OBJECTS) $(libfco_a_DEPENDENCIES) + -rm -f libfco.a + $(libfco_a_AR) libfco.a $(libfco_a_OBJECTS) $(libfco_a_LIBADD) + $(RANLIB) libfco.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libfco_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/fco/fco.cpp b/src/fco/fco.cpp new file mode 100644 index 0000000..c89d019 --- /dev/null +++ b/src/fco/fco.cpp @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fco.cpp +// Date....: 05/10/99 +// Creator.: Robert DiFalco (rdifalco) +// +// Implementation for the FCO Package +// + +#include "stdfco.h" +#include "fco.h" // for: cFCO +#include "core/core.h" // for: cCore +#include "fcoerrors.h" // for: fco error table + +TSS_ImplementPackage( cFCO ) + +cFCO::cFCO() +{ + TSS_Dependency ( cCore ); + TSS_REGISTER_PKG_ERRORS ( fco ); +} + +//============================================================================= +// iFCO -- First Class Object Interface +//============================================================================= +iFCO::~iFCO() +{ +} + +// eof: fco.cpp diff --git a/src/fco/fco.h b/src/fco/fco.h new file mode 100644 index 0000000..392bc43 --- /dev/null +++ b/src/fco/fco.h @@ -0,0 +1,214 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fco.h +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// +// package: cFCO -- FCO package data access +// interface iFCO -- abstract first class object +// interface iFCOSet -- abstract set of iFCOs +// interface iFCOIter -- iterator over an iFCOSet +// + +#ifndef __FCO_H +#define __FCO_H + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "core/package.h" // for: TSS_DeclarePackage + +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" // for: iSerRefCountObj +#endif + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Forward Declarations +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +class cFCO; // cFCO is the Package Representation +class iFCO; +class cFCOName; +class cFCOPropVector; +class iFCOPropSet; +class iFCOVisitor; +class iFCOSet; +class iFCOIter; +class iFCOPropDisplayer; + + +//============================================================================= +// cFCO -- First Class Object Package +//============================================================================= +// SYNOPSIS: +// +// CONSTRAINTS: +// +// INVARIANTS: +// +// +TSS_BeginPackage( cFCO ) + + TSS_DECLARE_STRINGTABLE; + + public: + + cFCO(); // Used to construct dependencies + +TSS_EndPackage( cFCO ) + + +//============================================================================= +// iFCO -- First Class Object Interface +//============================================================================= +// SYNOPSIS: +// +// CONSTRAINTS: +// +// INVARIANTS: +// +// +class iFCO : public iSerRefCountObj +{ +public: + virtual void SetName(const cFCOName& name) = 0; + virtual const cFCOName& GetName() const = 0; + // returns the name that uniquely identifies the fco in whatever system + // it lives in. Reference is valid as long as the fco exists + + virtual const iFCOPropSet* GetPropSet() const = 0; + virtual iFCOPropSet* GetPropSet() = 0; + // returns a pointer to the FCO's property set. It is to be destroyed + // by the FCO and is only guarenteed to be valid through the life of the + // fco. + + virtual uint32 GetCaps() const = 0; + // returns a bitmask that indicates properties that this object has. + // see the enum below for what the caps can contain + + virtual iFCO* Clone() const = 0; + // return a copy of the fco, with a reference count of 1. + // note that this will return an iFCO with _no_ children. If you want the + // child information, it should be copied manually + + virtual void AcceptVisitor(iFCOVisitor* pVisitor) = 0; + // visitor interface + + virtual void TraceContents(int debugLevel = -1) const {} + // spit the contents of the fco to debug out. -1 means to use D_DEBUG + + //-------------------------------- + // GetCaps() enumeration + //-------------------------------- + enum Caps + { + CAP_CAN_HAVE_CHILDREN = 0x1, + CAP_CAN_HAVE_PARENT = 0x2, + CAP_GENRE_SPECIFIC = 0x4 // start the genre-specific caps here. + }; + +protected: + virtual ~iFCO(); +}; + +class iFCOIter +{ +public: + virtual void SeekBegin() const = 0; + // seeks to the beginning of the set + virtual bool Done() const = 0; + // returns true if the iterator has gone past the end of the set + virtual bool IsEmpty() const = 0; + // is the set empty? + virtual void Next() const = 0; + // seek to the next element in the set + + virtual const iFCO* FCO() const = 0; + virtual iFCO* FCO() = 0; + // methods for getting the FCO that the iterator is currently pointing at + + virtual bool SeekToFCO(const cFCOName& name) const = 0; + // seeks the iterator to the fco specified by "name". If an fco by that name doesn't exist, + // false is returned and the iterator points at the end of the list (Done() will return true + + virtual void Remove() = 0; + virtual void Remove() const = 0; + // removes the fco pointed to by the iter. Behavior is undefined if the set is empty. + // after the erase, the iterator points to the next element in the list + + virtual void DestroyIter() const = 0; + // call this instead of delete()ing it. Since the FCOSet created this iterator, + // destruction with this method allows the object to "give" itself back to the + // FCOSet. + +protected: + virtual ~iFCOIter() {}; +}; + +class iFCOSet : public iTypedSerializable +{ +public: + virtual ~iFCOSet() {}; + + virtual const iFCOIter* Lookup(const cFCOName& name) const = 0; + virtual iFCOIter* Lookup(const cFCOName& name) = 0; + // returns a pointer to the FCO specified by "name" if it exists + // in the set, otherwise returns NULL. This will always map uniquely to a + // single FCO, since it is an error to have multiple FCOs with the same name in the set. + + virtual const iFCOIter* GetIter() const = 0; + virtual iFCOIter* GetIter() = 0; + // returns an iterator on the set + + virtual void Insert(iFCO* pFCO) = 0; + // inserts an fco into the set. The set will increment the reference count of the fco, and + // release it when the fco is removed from the set of the set is destroyed. + + virtual void Clear() = 0; + // clears out all the elements from the set + + virtual bool IsEmpty() const = 0; + virtual int Size() const = 0; + + virtual void TraceContents(int debugLevel = -1) const {} + // traces the contents of the spec to wherever cDebug is pointing; not pure + // virtual so that one is not forced to implement it. + // -1 means to use D_DEBUG + +}; + + +#endif//__FCO_H + diff --git a/src/fco/fcocompare.cpp b/src/fco/fcocompare.cpp new file mode 100644 index 0000000..bb1ee1e --- /dev/null +++ b/src/fco/fcocompare.cpp @@ -0,0 +1,116 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcocompare.cpp +// + +#include "stdfco.h" + +#include "fcocompare.h" +#include "core/debug.h" +#include "fco.h" +#include "fcoprop.h" +#include "fcopropset.h" +#include "core/errorutil.h" + +cFCOCompare::cFCOCompare() +{ + +} + +cFCOCompare::cFCOCompare( const cFCOPropVector& propsToCompare) +: mPropsToCmp( propsToCompare ) +{ + +} + +cFCOCompare::~cFCOCompare() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// Compare +/////////////////////////////////////////////////////////////////////////////// +uint32 cFCOCompare::Compare(const iFCO* pFco1, const iFCO* pFco2) +{ + ASSERT(pFco1 != 0); + ASSERT(pFco2 != 0); + // first, make sure the fcos are of the same type... + if(pFco1->GetType() != pFco2->GetType()) + { + ASSERT( false ); + INTERNAL_ERROR( "fcocompare.cpp" ); + } + + + const iFCOPropSet* ps1 = pFco1->GetPropSet(); + const iFCOPropSet* ps2 = pFco2->GetPropSet(); + const cFCOPropVector& v1 = pFco1->GetPropSet()->GetValidVector(); + const cFCOPropVector& v2 = pFco2->GetPropSet()->GetValidVector(); + + uint32 result = 0; + + mInvalidProps.SetSize( v1.GetSize() ); + mUnequalProps.SetSize( v1.GetSize() ); + mInvalidProps.Clear(); + mUnequalProps.Clear(); + + // finally, comapre all the properties + for(int i=0; iGetPropAt(i)->Compare(ps2->GetPropAt(i), iFCOProp::OP_EQ) != iFCOProp::CMP_TRUE) + { + // they are not equal! + mUnequalProps.AddItem(i); + result |= PROPS_UNEQUAL; + } + } + } + } + + if( ! result ) + result = EQUAL; + + return result; +} + diff --git a/src/fco/fcocompare.h b/src/fco/fcocompare.h new file mode 100644 index 0000000..d49a915 --- /dev/null +++ b/src/fco/fcocompare.h @@ -0,0 +1,107 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcocompare.h +// +// iFCOCompare -- interface for object that compares FCO properties +#ifndef __FCOCOMPARE_H +#define __FCOCOMPARE_H + +#ifndef __FCOPROPVECTOR_H +#include "fcopropvector.h" +#endif + +class iFCO; + +class cFCOCompare +{ +public: + enum Result + { + EQUAL = 1, + PROPS_UNEQUAL = 2, + PROPS_NOT_ALL_VALID = 4 + }; + + cFCOCompare(); + cFCOCompare( const cFCOPropVector& propsToCompare); + virtual ~cFCOCompare(); + + void SetPropsToCmp(const cFCOPropVector& pv); + const cFCOPropVector& GetPropsToCmp() const; + // gets and sets the property vector that indicates what properties the + // object will consider in the comparisons. + + uint32 Compare(const iFCO* pFco1, const iFCO* pFco2) ; + // compares fco1 and fco2, only considering the properties specified set with + // SetPropsToCmp(). The result of the comparison is a bitmask that is currently either + // EQUAL or a combination of PROPS_NOT_ALL_VALID and PROPS_UNEQUAL. You can discover which + // properties caused these return flags with the GetXXXProps() methods below. + // NOTE -- in integrity checking, the old fco should be the first parameter and the new fco the + // second (to support growing files properly) + + const cFCOPropVector& GetInvalidProps() const; + // only meaningful if the last Compare() returned PROPS_NOT_ALL_VALID + const cFCOPropVector& GetUnequalProps() const; + // only meaningful if the last Compare() returned PROPS_UNEQUAL + +private: + cFCOPropVector mPropsToCmp; + cFCOPropVector mInvalidProps; + cFCOPropVector mUnequalProps; +}; + +///////////////////////////////////////////////////////////// +// inline implementation +inline void cFCOCompare::SetPropsToCmp(const cFCOPropVector& pv) +{ + mPropsToCmp = pv; +} + +inline const cFCOPropVector& cFCOCompare::GetPropsToCmp() const +{ + return mPropsToCmp; +} + +inline const cFCOPropVector& cFCOCompare::GetInvalidProps() const +{ + return mInvalidProps; +} + +inline const cFCOPropVector& cFCOCompare::GetUnequalProps() const +{ + return mUnequalProps; +} + + +#endif //__FCOCOMPARE_H + diff --git a/src/fco/fcocompare_t.cpp b/src/fco/fcocompare_t.cpp new file mode 100644 index 0000000..123d872 --- /dev/null +++ b/src/fco/fcocompare_t.cpp @@ -0,0 +1,157 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcocompare_t.cpp -- the compare object's test driver +#include "stdfco.h" +#include "fcocompare.h" +#include "core/debug.h" +#include "fs/fsobject.h" +#include "fs/fspropcalc.h" +#include "test/test.h" + +#include + +/////////////////////////////////////////////////////////////////////////////// +// PrintProps -- prints out all the valid property names and values as pairs... +/////////////////////////////////////////////////////////////////////////////// +/* +static void PrintProps(const iFCO* pFCO) +{ + cDebug d("PrintProps"); + const iFCOPropSet* pSet = pFCO->GetPropSet(); + const cFCOPropVector& v = pSet->GetValidVector(); + + for(int i=0; iGetNumProps(); i++) + { + if(v.ContainsItem(i)) + { + d.TraceDebug(_T("[%d] %s\t%s\n"), i, pSet->GetPropName(i).c_str(), pSet->GetPropAt(i)->AsString().c_str()); + } + } +} +*/ + +void TestFCOCompare() +{ +#pragma message( __FILE__ "(1) : TODO - implement this test file") +#if 0 + + const TCHAR* FILE_NAME = TEMP_DIR _T("/dog.txt"); + const char* FILE_NAME_N = TEMP_DIR_N "/dog.txt"; + + cDebug d("TestFCOCompare"); + d.TraceDebug("Entering...\n"); + + // first, create an fco to compare with... + + TOFSTREAM fstr(FILE_NAME_N); + if(fstr.bad()) + { + d.TraceError("Unable to create test file %s!\n", FILE_NAME); + TEST(false); + return; + } + + fstr << "Bark! Bark! Bark!" << std::endl; + fstr.close(); + + // create the test FCO + cFSDataSource ds; + iFCO* pFCO = ds.CreateFCO(cFCOName(FILE_NAME), 0); + TEST(pFCO); + + // measure a couple of properties, some of which will change... + cFSPropCalc propCalc; + cFCOPropVector v(pFCO->GetPropSet()->GetValidVector().GetSize()); + v.AddItem(cFSPropSet::PROP_DEV); + v.AddItem(cFSPropSet::PROP_CTIME); + v.AddItem(cFSPropSet::PROP_SIZE); + v.AddItem(cFSPropSet::PROP_MTIME); + v.AddItem(cFSPropSet::PROP_FILETYPE); + v.AddItem(cFSPropSet::PROP_GROWING_FILE); + propCalc.SetPropVector(v); + pFCO->AcceptVisitor(&propCalc); + d.TraceDebug("First FCO's properties:\n"); + PrintProps(pFCO); + + // first, try comparing it to itself... + cFCOCompare comp; + cFCOCompare::CompareResult result; + comp.SetPropsToCmp(v); + comp.Compare(pFCO, pFCO, result); + d.TraceDebug("Compare to itself is (expect true) %s\n", result.mResult == cFCOCompare::EQUAL? "true" : "false"); + TEST(result.mResult == cFCOCompare::EQUAL); + + // change the file... + d.TraceDebug("Changing the file...\n"); + fstr.open(FILE_NAME_N); + if(fstr.bad()) + { + d.TraceError("Unable to reopen %s!\n", FILE_NAME_N); + TEST(false); + return; + } + fstr << "Meow! Meow! Meow! Meow!" << std::endl; + fstr.close(); + + iFCO* pFCO2 = ds.CreateFCO(cFCOName(FILE_NAME), 0); + ASSERT(pFCO2); + pFCO2->AcceptVisitor(&propCalc); + d.TraceDebug("Second FCO's properties:\n"); + PrintProps(pFCO2); + + comp.Compare(pFCO, pFCO2, result); + d.TraceDebug("Compare to new object is (expect false) %s\n", result.mResult == cFCOCompare::EQUAL? "true" : "false"); + TEST(result.mResult == cFCOCompare::UNEQUAL); + d.TraceDebug("Properties that differ are:\n"); + result.mPropVector.TraceContents(); + + // try testing properties that weren't calculated... + d.TraceDebug("Comparing FCOs with different properties calculated\n"); + iFCO* pFCO3 = ds.CreateFCO(cFCOName(FILE_NAME), 0); + v = propCalc.GetPropVector(); + v.AddItem(cFSPropSet::PROP_MD5); + propCalc.SetPropVector(v); + pFCO3->AcceptVisitor(&propCalc); + // do the compare + comp.SetPropsToCmp(v); + comp.Compare(pFCO2, pFCO3, result); + TEST(result.mResult == cFCOCompare::PROPS_NOT_ALL_VALID); + d.TraceDebug("Properties not valid are (should be %d):\n", cFSPropSet::PROP_MD5); + result.mPropVector.TraceContents(); + + // release the fcos + pFCO3->Release(); + pFCO2->Release(); + pFCO->Release(); +#endif + return; +} diff --git a/src/fco/fcodatasource.h b/src/fco/fcodatasource.h new file mode 100644 index 0000000..a80ccf2 --- /dev/null +++ b/src/fco/fcodatasource.h @@ -0,0 +1,80 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatasource.h +// +// iFCODataSource -- interface to an object that can create FCOs given a cFCOName +#ifndef __FCODATASOURCE_H +#define __FCODATASOURCE_H + +class iFCO; +class cFCOName; +class cFCOErrorQueue; + +class iFCODataSource +{ +public: + enum { CHILDREN_NONE = 0, + CHILDREN_ALL = -1 }; + + // NOTE -- in the act of creating fcos, there are certain properties that we can obtain "for free" just + // by the act of querying the system we are generating fcos for (for example, a stat() call is required + // to create file system fcos, which also gives us many of the fsfco's property values). Therefore, + // as an optimization, fcos returned from this interface might have some properties filled out. If that + // is not desireable, you should call iFCO::GetPropSet()->Clear() to invalidate all the properties. + + virtual iFCO* CreateFCO(const cFCOName& name, int recurseDepth, cFCOErrorQueue* pQueue = 0) const = 0; + // creates the FCO specified by "name", returns NULL if the object doesn't exist + // on the system the data source is bound to. recurseDepth is how deep the child + // tree should be built; 0 means get no children, and -1 means all the children + // All errors that occur will be reported to the passed in error bucket; it is ok to pass + // NULL if you don't care about errors. + + virtual bool GetChildren(iFCO* pFCO, int recurseDepth, cFCOErrorQueue* pQueue = 0) const = 0; + // given a pointer to an FCO, this will populate it with children for as many levels + // as specified by recursedepth. The passed in FCO should have no children; it is + // undefined what will happen to existing children after this function returns. + // All errors that occur will be reported to the passed in error bucket; it is ok to pass + // NULL if you don't care about errors. + + // cErrorBucket error numbers... + // the data source owns all error numbers from 100-199 + enum ErrorNum + { + ERR_READDIR_FAIL = 100, + ERR_GETFILETYPE_FAIL = 101, + ERR_NUM_ERRORS + }; +}; + +#endif + diff --git a/src/fco/fcodatasourceiter.cpp b/src/fco/fcodatasourceiter.cpp new file mode 100644 index 0000000..b070681 --- /dev/null +++ b/src/fco/fcodatasourceiter.cpp @@ -0,0 +1,67 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatasourceiter,cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfco.h" +#include "fcodatasourceiter.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +iFCODataSourceIter::Relationship iFCODataSourceIter::Compare( const TCHAR* str1, const TCHAR* str2 ) const +{ + int cmpResult; + if( IsCaseSensitive() ) + { + cmpResult = _tcscmp( str1, str2 ); + } + else + { + cmpResult = _tcsicmp( str1, str2 ); + } + + if ( cmpResult < 0 ) + return REL_LT; + else if ( cmpResult > 0 ) + return REL_GT; + else + return REL_EQ; + +} + diff --git a/src/fco/fcodatasourceiter.h b/src/fco/fcodatasourceiter.h new file mode 100644 index 0000000..709ef9e --- /dev/null +++ b/src/fco/fcodatasourceiter.h @@ -0,0 +1,207 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatasourceiter.h +// +// iFCODataSourceIter -- the data source iterator base class +// +#ifndef __FCODATASOURCEITER_H +#define __FCODATASOURCEITER_H + +//========================================================================= +// INCLUDES +//========================================================================= + + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +#ifndef __FCONAME_H +#include "fconame.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class iFCO; +class cErrorBucket; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//----------------------------------------------------------------------------- +// eFCODataSourceIter +//----------------------------------------------------------------------------- +/* +class eFCODataSourceIter : public eError +{ +public: + // TODO -- this class should contain another exception as a member variable that + // represents the exception thrown from the underlying subsystem + + enum + { + ERR_MIN = 1600, + ERR_DUPE_FCO, + ERR_MAX + }; + + eFCODataSourceIter(int errorNum, const TSTRING& msg) : eError( errorNum, msg ) {} +}; +*/ +TSS_EXCEPTION( eFCODataSourceIter, eError ) +TSS_EXCEPTION( eFCODataSourceIterDupeFCO, eFCODataSourceIter ) + +//----------------------------------------------------------------------------- +// iFCODataSourceIter +//----------------------------------------------------------------------------- +class iFCODataSourceIter +{ +public: + + // + // constructor + // + iFCODataSourceIter() {} + virtual ~iFCODataSourceIter() {} + + virtual iFCODataSourceIter* CreateCopy() const = 0; + // this creates a new iterator that is an exact copy of myself; it is the caller's responsibility + // to delete the return value of this method + + virtual const TCHAR* GetShortName() const = 0; + virtual cFCOName GetName() const = 0; + virtual cFCOName GetParentName() const = 0; + // this returns the current node name, the fully qualified node name, and the node's parent's name + // respectively. The first two methods return undefined strings if Done() is true. + + // + // traverse up and down the hierarchy + // + virtual bool AtRoot() const = 0; //throw (eError) + virtual bool CanDescend() const = 0; //throw (eError) + virtual void Descend() = 0; //throw (eError) = 0 + virtual void Ascend() = 0; //throw (eError) = 0 + + // + // traverse my peers (objects in the same directory as me) + // + virtual void SeekBegin() = 0; + virtual bool Done() const = 0; + virtual void Next() = 0; + + // + // actually getting the fco + // + virtual iFCO* CreateFCO() = 0; //throw (eError) = 0 + virtual void SeekToFCO(const cFCOName& name, bool bCreatePeers = true) = 0; //throw (eFCODataSourceIter) = 0 + // I actually think that this method should just set Done() == true if the + // object doesn't exist, besides adding something to the error bucket. + // bCreatePeers is a hint to the iterator. Set it to false if you are only interested in the named + // FCO and/or its children. If it is set to false, the iterator may opt to not create the named + // FCO's peers, if that will speed up the operation. + + virtual void SetErrorBucket( cErrorBucket* pBucket) = 0; + // call this to set the error queue; internal errors that occur while generating fcos + // will have their messages posted to the error queue. To remove the error queue, call + // this with NULL as the single parameter + + virtual bool SeekTo( const TCHAR* shortName ) = 0; + // this looks among my peers for an entry named shortName. It takes case-sensitiveness + // into account. If the object is not found, Done() is true after this and false is returned. + + virtual bool IsCaseSensitive() const = 0; + // override this to indicate whether the underlying data source is case sensitive + + enum IterFlags + { + DO_NOT_MODIFY_OBJECTS = 0x00000001 // reset any object properties that may have been altered due to iteration + }; + virtual int GetIterFlags() const = 0; + virtual void SetIterFlags(int i) = 0; + // any flags needed for iteration. + + + //TODO - should the iterator have insertion or deletion methods? + // It seems to me that insertion is necessary for rapid database creation, but deletion is + // probably not necessary (although nice for symmetry). It also seems that we would want the + // + + //------------------------------------------------------------------------- + // non-pure virtual methods + //------------------------------------------------------------------------- + + // + // getting my relationship to other data source iters... + // + enum Relationship + { + REL_LT, //less than + REL_EQ, //equal + REL_GT //greater than + }; + Relationship GetRelationship(const iFCODataSourceIter& rhs) const; + // this returns the relationship of the currently pointed-at item in my list to + // the current one in the rhs's list. It is assumed that the parent name is the same + // for both sides, asserted that both sides are not Done(), and asserted that + // the case-sensitiveness of both sides is the same. + // + // TODO -- If I implement this with string compares of the short name, is this + // going to be too slow? If so, I might need to add the GetShortHash() method + // to this interface that would return some simple hash of the short name. + Relationship Compare( const TCHAR* str1, const TCHAR* str2 ) const; + // this compares str1 to str2 and returns lt, eq, or gt. All iterators should use + // this method to order the short names of the objects that they iterate over. +}; + + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + +inline iFCODataSourceIter::Relationship iFCODataSourceIter::GetRelationship(const iFCODataSourceIter& rhs) const +{ + ASSERT( IsCaseSensitive() == + rhs.IsCaseSensitive() ); + + return ( Compare( GetShortName(), rhs.GetShortName() ) ); +} + +#endif //__FCODATASOURCEITER_H + diff --git a/src/fco/fcodatasourceiterimpl.cpp b/src/fco/fcodatasourceiterimpl.cpp new file mode 100644 index 0000000..a9846db --- /dev/null +++ b/src/fco/fcodatasourceiterimpl.cpp @@ -0,0 +1,466 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatasourceiterimpl.cpp +// + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfco.h" +#include "fcodatasourceiterimpl.h" +#include "fco.h" +#include "core/upperbound.h" +#include "core/errorbucket.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +cFCODataSourceIterImpl::cFCODataSourceIterImpl() + : mFlags(0) +{ +} + + +cFCODataSourceIterImpl::~cFCODataSourceIterImpl() +{ + ClearList(); +} + +/////////////////////////////////////////////////////////////////////////////// +// operator = +/////////////////////////////////////////////////////////////////////////////// +cFCODataSourceIterImpl& cFCODataSourceIterImpl::operator=( const cFCODataSourceIterImpl& rhs ) +{ + ClearList(); + mPeers = rhs.mPeers; + mParentName = rhs.mParentName; + mpErrorBucket = rhs.mpErrorBucket; + mFlags = rhs.mFlags; + // + // we need to addref all of the fcos we just got... + // + for( FCOList::const_iterator i = mPeers.begin(); i != mPeers.end(); i++ ) + { + (*i)->AddRef(); + } + // + // figuring out where to put the iterator is a little trickier... + // TODO -- if we ever change the mPeers data structure from a vector, this will + // have to change (luckily, the compiler should catch this!) + // + if( rhs.Done() ) + { + mCurPos = mPeers.end(); + } + else + { + int offset = rhs.mCurPos - rhs.mPeers.begin(); + mCurPos = mPeers.begin() + offset; + } + + return *this; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetShortName +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cFCODataSourceIterImpl::GetShortName() const +{ + ASSERT( ! Done() ); + + return ( (*mCurPos)->GetName().GetShortName() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetName +/////////////////////////////////////////////////////////////////////////////// +cFCOName cFCODataSourceIterImpl::GetName() const +{ + ASSERT( ! Done() ); + + return ( (*mCurPos)->GetName() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetParentName +/////////////////////////////////////////////////////////////////////////////// +cFCOName cFCODataSourceIterImpl::GetParentName() const +{ + return mParentName; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetParentName +/////////////////////////////////////////////////////////////////////////////// +bool cFCODataSourceIterImpl::AtRoot() const //throw (eError) +{ + return ( mParentName.GetSize() == 0 ); +} + +/////////////////////////////////////////////////////////////////////////////// +// CanDescend +/////////////////////////////////////////////////////////////////////////////// +bool cFCODataSourceIterImpl::CanDescend() const //throw (eError) +{ + ASSERT( ! Done() ); + if( Done() ) + { + return false; + } + + return ( (*mCurPos)->GetCaps() & iFCO::CAP_CAN_HAVE_CHILDREN ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Descend +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::Descend() //throw (eError) +{ + ASSERT( CanDescend() ); + + mParentName = GetName(); + GeneratePeers( ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Ascend +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::Ascend() //throw (eError) +{ + ASSERT( ! AtRoot() ); + + cFCOName name = mParentName; + SeekToFCO( name ); // I do this because SeekToFCO modifies mCwd and takes a reference parameter. +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekBegin +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::SeekBegin() +{ + mCurPos = mPeers.begin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Done +/////////////////////////////////////////////////////////////////////////////// +bool cFCODataSourceIterImpl::Done() const +{ + return ( mCurPos == mPeers.end() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Next +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::Next() +{ + mCurPos++; +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateFCO +/////////////////////////////////////////////////////////////////////////////// +iFCO* cFCODataSourceIterImpl::CreateFCO() //throw (eError) +{ + ASSERT( ! Done() ); + + if( ! InitializeTypeInfo( *mCurPos ) ) + return 0; + + (*mCurPos)->AddRef(); + return *mCurPos; +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekToFCO +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::SeekToFCO(const cFCOName& name, bool bCreatePeers) // throw (eFCODataSourceIter) +{ + ASSERT( name.GetSize() > 0 ); + ASSERT( name.IsCaseSensitive() == IsCaseSensitive() ); + + // + // get the parent name and pop the short child name + // + cFCOName parentName = name; + + parentName.Pop(); // RAD:05/10/1999 -- Used to assign result to "shortname" + + if( parentName.GetSize() == 0 ) + { + // we are going to the root directory... + // note that we are not responsible for iterating over the root nodes (for example, + // all of the drive letters in NT or all the hive names in the registry) + // + mParentName.Clear(); + ClearList(); + iFCO* pObj = CreateObject( name, bCreatePeers ); + if( ! pObj ) + { + // error creating object; just return. + return; + } + + InsertIntoPeers( pObj ); + mCurPos = mPeers.begin(); + return; + } + else + { + // if we are not creating our peers, simply create the single object and return... + // + if( ! bCreatePeers ) + { + ClearList(); + mParentName = parentName; + iFCO* pNewObj = CreateObject( name, false ); + if( pNewObj ) + { + InsertIntoPeers( pNewObj ); + mCurPos = mPeers.begin(); + } + return; + } + // + // otherwise, load up everything. Note that we can't do the if(parentName == mParentName) optimization + // because if you do a SeekToFCO( c:/foo, false) and then a SeekToFCO( c:/bar, true), it won't work + // correctly -- 27 Jan 99 mdb + // + mParentName = parentName; + ClearList(); + GeneratePeers(); + } + + SeekToPeerByName( (*mCurPos)->GetName().GetShortName() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// IsCaseSensitive +/////////////////////////////////////////////////////////////////////////////// +bool cFCODataSourceIterImpl::IsCaseSensitive() const +{ + return mParentName.IsCaseSensitive(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ClearList +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::ClearList() +{ + for( mCurPos = mPeers.begin(); mCurPos != mPeers.end(); mCurPos++ ) + { + (*mCurPos)->Release(); + } + + mPeers.clear(); + mCurPos = mPeers.end(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// GeneratePeers +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::GeneratePeers() +{ + ///TODO -- BIG BIG TODO -- I need to implement some lazy evaluation for these + // fcos so that when I seek to a start point, I don't stat everything in the + // same directory as myself. + // NOTE: This might be alleviated by differentiating between seeks that need + // peers and ones that do not (or maybe lazy evaluation of the peers) + + ClearList(); + + // + // read all of the children of the parent... + // + std::vector vChildrenNames; + GetChildrenNames( mParentName.AsString(), vChildrenNames ); + + // + // insert the children into the set... + // + std::vector::iterator i; + cFCOName curName = mParentName; + for( i = vChildrenNames.begin(); i != vChildrenNames.end(); i++) + { + curName.Push( *i ); + + iFCO* pNewObj = CreateObject( curName, true ); + if( pNewObj ) + { + if( ! InsertIntoPeers( pNewObj ) ) + { + // no need for an error msg; that is handled by InsertIntoPeers; + // just release the object. + // + pNewObj->Release(); + } + } + curName.Pop(); + } + + mCurPos = mPeers.begin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +bool cFCODataSourceIterImpl::SeekTo( const TCHAR* shortName ) +{ + FCOList::iterator i = UpperBound( shortName ); + if( i != mPeers.end() ) + { + if( REL_EQ == Compare( shortName, (*i)->GetName().GetShortName() ) ) + { + mCurPos = i; + return true; + } + } + + mCurPos = mPeers.end(); + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::TraceContents(int dl) const +{ + if( dl == -1 ) + dl = cDebug::D_DEBUG; + + cDebug d("cFCODataSourceIterImpl::TraceContents"); + + d.Trace( dl, "FCO Iterator; parent = %s\n", mParentName.AsString().c_str() ); + d.Trace( dl, "---- Peers ---- (current has a * by it)\n" ); + int cnt = 0; + for( FCOList::const_iterator iter = mPeers.begin(); iter != mPeers.end(); iter++, cnt++ ) + { + d.Trace( dl, "[%d]%c\t:%s\n", cnt, iter == mCurPos ? _T('*') : _T(' '), (*iter)->GetName().AsString().c_str() ); + } + d.Trace( dl, "--------------- \n" ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// InsertIntoPeers +/////////////////////////////////////////////////////////////////////////////// +// inserts the fco into peers. +// Sorted in increasing order by short name of the FCO. +bool cFCODataSourceIterImpl::InsertIntoPeers( iFCO* pFCO ) +{ + FCOList::iterator i = UpperBound( pFCO->GetName().GetShortName() ); + + if( i != mPeers.end() ) + { + // never insert two objects that have the same name... + // + if( REL_EQ == Compare( pFCO->GetName().GetShortName(), (*i)->GetName().GetShortName() ) ) + { + mpErrorBucket->AddError( eFCODataSourceIterDupeFCO( pFCO->GetName().AsString(), eError::NON_FATAL ) ); + return false; + } + else + mPeers.insert( i, pFCO ); + } + else + mPeers.push_back( pFCO ); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekToPeerByName +/////////////////////////////////////////////////////////////////////////////// +void cFCODataSourceIterImpl::SeekToPeerByName( const TCHAR* pchName ) +{ + FCOList::iterator i = UpperBound( pchName ); + if( i != mPeers.end() ) + { + if( REL_EQ == Compare( pchName, (*i)->GetName().GetShortName() ) ) + { + mCurPos = i; + return; + } + } + + mCurPos = mPeers.end(); +} + +/////////////////////////////////////////////////////////////////////////////// +// CompareShortName +/////////////////////////////////////////////////////////////////////////////// + +bool cFCODataSourceIterImpl::CompareForUpperBound( const iFCO* pFCO, const TCHAR* pchName ) const +{ + return( Compare( pFCO->GetName().GetShortName(), pchName ) == REL_LT ); +} + +/////////////////////////////////////////////////////////////////////////////// +// cFCODataSourceIterImplCallCompare +// -- used to sneak a pointer-to-member-function where a +// pointer-to-non-member-function is expected +/////////////////////////////////////////////////////////////////////////////// + +class cFCODataSourceIterImplCallCompare +{ +public: + cFCODataSourceIterImplCallCompare( const cFCODataSourceIterImpl* pcls ) + : pc( pcls ) {}; + + bool operator()( const iFCO* a1, const TCHAR* a2 ) + { + return pc->CompareForUpperBound( a1, a2 ); + } + +private: + const cFCODataSourceIterImpl* pc; +}; + +/////////////////////////////////////////////////////////////////////////////// +// UpperBound +/////////////////////////////////////////////////////////////////////////////// + +cFCODataSourceIterImpl::FCOList::iterator cFCODataSourceIterImpl::UpperBound( const TCHAR* pchShortName ) +{ + cFCODataSourceIterImplCallCompare comp( this ); + return ::UpperBound( mPeers.begin(), mPeers.end(), pchShortName, comp ); +} + diff --git a/src/fco/fcodatasourceiterimpl.h b/src/fco/fcodatasourceiterimpl.h new file mode 100644 index 0000000..2816938 --- /dev/null +++ b/src/fco/fcodatasourceiterimpl.h @@ -0,0 +1,182 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsdatasourceiter.h +// +#ifndef __FCODATASOURCEITERIMPL_H +#define __FCODATASOURCEITERIMPL_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __FCODATASOURCEITER_H +#include "fcodatasourceiter.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + + +class cFCODataSourceIterImpl : public iFCODataSourceIter +{ +public: + cFCODataSourceIterImpl(); + virtual ~cFCODataSourceIterImpl(); + cFCODataSourceIterImpl& operator=( const cFCODataSourceIterImpl& rhs ); + + + virtual const TCHAR* GetShortName() const; + virtual cFCOName GetName() const; + virtual cFCOName GetParentName() const; + + virtual bool AtRoot() const; //throw (eError); + virtual bool CanDescend() const; //throw (eError); + virtual void Descend(); //throw (eError); + virtual void Ascend(); //throw (eError); + + virtual void SeekBegin(); + virtual bool Done() const; + virtual void Next(); + + virtual iFCO* CreateFCO(); //throw (eError); + virtual void SeekToFCO(const cFCOName& name, bool bCreatePeers = true); //throw (eFCODataSourceIter); + + virtual void SetErrorBucket( cErrorBucket* pBucket ) { mpErrorBucket = pBucket; } + virtual bool SeekTo( const TCHAR* shortName ); + virtual bool IsCaseSensitive() const; + + virtual int GetIterFlags() const; + virtual void SetIterFlags(int i); + + + // + // must override this functions + // + virtual iFCODataSourceIter* CreateCopy() const = 0; + + // debug functions + virtual void TraceContents(int dl = -1) const; + + + // + // util function for sorting/searching + // + bool CompareForUpperBound( const iFCO* pFCO, const TCHAR* pchName ) const; + // compares shortname of FCO to pchName. returns < == or > 0 as strcmp does. + +protected: + cFCODataSourceIterImpl( const cFCODataSourceIterImpl& ); + + //TODO -- turn this into a set? + // + typedef std::vector FCOList; // sorted in increasing order by name of the FCO + + cErrorBucket* mpErrorBucket; + cFCOName mParentName; + FCOList mPeers; + FCOList::const_iterator mCurPos; + uint32 mFlags; + + //------------------------------------------------------------------------- + // helper methods + //------------------------------------------------------------------------- + void GeneratePeers(); + // used to implement Descend() -- also used by SeekToFCO() ... it takes the value of + // mParentName and fills out mPeers and sets mCurPos to mPeers.begin() + // TODO -- this fills out the error queue if the readdir() or any stats fail. + void ClearList(); + // releases everything in the list, empties the list, and sets mCurPos to end() + + bool InsertIntoPeers( iFCO* pFCO ); + // inserts the fco into peers. Peers sorted in increasing order by name of the FCO. + // Uses binary search to find location into which to insert. + // mCurPos is not guaranteed to be valid after this call due to possible list reallocation. + // If an entry with the same name already exists, the fco is not added, an error is added to the error + // bucket, and false is returned. Otherwise, true is always returned. + + void SeekToPeerByName( const TCHAR* pchName ); + // seeks the iter to the peer with this name. Done() will be true if the function cannot find the peer + // Uses binary search algorithm. + + FCOList::iterator UpperBound( const TCHAR* pchShortName ); + // same as std::upper_bound except it calls CompareForUpperBound() to + // do its comparison. + + + // + // must override these functions + // + virtual void GetChildrenNames( const TSTRING& strParentName, std::vector& vChildrenNames ) = 0; + // retrieves the names of all the children of the named parent + // strParent name is of the form returned by cFCOName::AsString. Note that it is not very efficient + // to do it this way for registry objects -- 4 Mar 99 mdb + + virtual iFCO* CreateObject(const cFCOName& name, bool bCreatingPeers ) = 0; + // this method is called when creating the heirarchy. at minimum it needs to create an empty iFCO + // with the correct name. if NULL is returned, the iterator does not go any deeper into the FCO. + // you may also use this call to set some properties of the FCO. For instance, + // FS will record the device number of a file if we are creating peers, and it's CreateObject will + // fail if it's peers have a different device number. + // Must set the object type in this function + // + // If bCreatingPeers is false, then this method needs to verify that the object actually exists, and + // return 0 if it does not. (if bCreatingPeers is true, we got the name from the OS, so we assume it + // exists) + + virtual bool InitializeTypeInfo(iFCO* pFCO) = 0; + // initializes the minimal amout of information about the fco to know what "type" it is. If any OS calls + // fail, the error bucket should be filled up and false should be returned. + // + // this method should check whether the properties are already valid and do nothing if they already are; + // this has the potential to be called multiple times, so we need to be efficient. + + +}; + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + +inline int cFCODataSourceIterImpl::GetIterFlags() const +{ + return mFlags; +} + +inline void cFCODataSourceIterImpl::SetIterFlags( int i ) +{ + mFlags = i; +} + +#endif //__FCODATASOURCEITERIMPL_H + diff --git a/src/fco/fcoerrors.cpp b/src/fco/fcoerrors.cpp new file mode 100644 index 0000000..163d3f9 --- /dev/null +++ b/src/fco/fcoerrors.cpp @@ -0,0 +1,49 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcoerrors.cpp +// +// Registers all error strings in the fco package +// + +#include "stdfco.h" +#include "fcoerrors.h" +#include "core/errortable.h" + +#include "fcodatasourceiter.h" + +TSS_BEGIN_ERROR_REGISTRATION( fco ) + +TSS_REGISTER_ERROR( eFCODataSourceIter(), _T("Data source error.") ) +TSS_REGISTER_ERROR( eFCODataSourceIterDupeFCO(), _T("Duplicate object encountered.") ) + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/fco/fcoerrors.h b/src/fco/fcoerrors.h new file mode 100644 index 0000000..89b4978 --- /dev/null +++ b/src/fco/fcoerrors.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fcoerrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __FCOERRORS_H +#define __FCOERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( fco ) + +#endif //__FCOERRORS_H + diff --git a/src/fco/fcogenre.h b/src/fco/fcogenre.h new file mode 100644 index 0000000..704a0f1 --- /dev/null +++ b/src/fco/fcogenre.h @@ -0,0 +1,102 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcogenre.h +// + +#ifndef __FCOGENRE_H +#define __FCOGENRE_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "core/types.h" + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//------------------------------------------------ +// class cGenre -- encapsulates genre ID +// information. Also a non-code +// registry for genre IDs. +//------------------------------------------------ +class cGenre +{ +public: + typedef uint32 Genre; + + + //----------------------------------------- + // Valid Platforms -- static and commpiled + //----------------------------------------- + enum Platform + { + PLATFORM_MASK_INVALID = 0x00000000, + PLATFORM_MASK_NT = 0x00010000, + PLATFORM_MASK_UNIX = 0x00020000 + }; + + //-------------------------------------------------------------------- + // Valid Genres -- dynamic so not compiled except for 'invalid' value + //-------------------------------------------------------------------- + enum ValidGenres + { + //--------------------------------------------------------------- + // this the non-compiled registry of genre IDs. + // all genre IDs should be listed here to avoid any + // duplicate IDs. + //--------------------------------------------------------------- + + /* + GENRE_NTFS = 0x00010001, + GENRE_NTREG = 0x00010002, + GENRE_FS = 0x00020001, + */ + GENRE_INVALID = 0x00000000 + }; + + //---------------------------------------- + // don't let C++ create default functions + //---------------------------------------- + cGenre(); + ~cGenre(); + cGenre( const cGenre& ); + cGenre& operator=( const cGenre& ); + cGenre* operator&(); + const cGenre* operator&() const; + +}; // eoc: cGenre + +#endif // __FCOGENRE_H + diff --git a/src/fco/fconame.cpp b/src/fco/fconame.cpp new file mode 100644 index 0000000..312c94b --- /dev/null +++ b/src/fco/fconame.cpp @@ -0,0 +1,690 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconame.cpp +/////////////////////////////////////////////////////////////////////////////// +#include "stdfco.h" +#include "fconame.h" +#include "core/serializer.h" +#include "fconametbl.h" +#include "core/refcountobj.h" +#include "twfactory.h" +#include "core/errorutil.h" +#include "core/ntmbs.h" + +#include + +//############################################################################# +// cFCOName_i -- an implementation of a cFCOName -- this object is refrence +// counted (so copies are cheap) and contains a linked list of cFCOTableNodes +// as well as the static instance of the cFCONameTbl. +//############################################################################# +class cFCOName_i : public cRefCountObj +{ +public: + cFCOName::ListType mNames; + + ~cFCOName_i() { ClearList(); } + void ClearList(); + // releases all the names in mNames and clears the list + + // the single name table + static cFCONameTbl msNameTbl; +}; + +/////////////////////////////////////////////////// +// ClearList() +/////////////////////////////////////////////////// +inline void cFCOName_i::ClearList() +{ + cFCOName::ListType::iterator i; + for(i = mNames.begin(); i != mNames.end(); ++i) + (*i)->Release(); + mNames.clear(); +} + +cFCONameTbl cFCOName_i::msNameTbl; + +//############################################################################# +// cFCOName +//############################################################################# +IMPLEMENT_TYPEDSERIALIZABLE(cFCOName, _T("cFCOName"), 0, 1) + +/////////////////////////////////////////////////////////////////////////////// +// ClearNameTable -- IMPORTANT!!! This should only be called when you are 100% +// positive no more operations involving fco names will occur. +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::ClearNameTable() +{ + cFCOName_i::msNameTbl.Clear(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cFCOName::cFCOName(iFCONameInfo* pNI) : + mpPathName(0) +{ + SetNameInfo(pNI); + mpPathName = new cFCOName_i; +#ifdef _DEBUG + mDebugStrName = AsString(); + cDebug d("cFCOName::cFCOName(iFCONameInfo*)"); + d.TraceNever(_T("constructing %X:%X %s (refcount=%d)\n"), this, mpPathName, mDebugStrName.c_str(), mpPathName->GetRefCount()); +#endif +} + +cFCOName::cFCOName(const cFCOName& rhs) : + mpPathName(rhs.mpPathName), + mDelimiter(rhs.mDelimiter), + mbCaseSensitive(rhs.mbCaseSensitive) +{ + mpPathName->AddRef(); +#ifdef _DEBUG + mDebugStrName = AsString(); + cDebug d("cFCOName::cFCOName(cFCOName&)"); + d.TraceNever(_T("constructing %X:%X %s (refcount=%d)\n"), this, mpPathName, mDebugStrName.c_str(), mpPathName->GetRefCount()); +#endif +} + +cFCOName::cFCOName(const TSTRING& rhs, iFCONameInfo* pNI) : + mpPathName(0) +{ + SetNameInfo(pNI); + mpPathName = new cFCOName_i; + ParseString(rhs.c_str()); + +#ifdef _DEBUG + mDebugStrName = AsString(); + cDebug d("cFCOName::cFCOName(cFCOName&,iFCONameInfo*)"); + d.TraceNever(_T("constructing %X:%X %s (refcount=%d)\n"), this, mpPathName, mDebugStrName.c_str(), mpPathName->GetRefCount()); +#endif +} + +cFCOName::cFCOName(const TCHAR* rhs, iFCONameInfo* pNI) : + mpPathName(0) +{ + SetNameInfo(pNI); + mpPathName = new cFCOName_i; + ParseString(rhs); + +#ifdef _DEBUG + mDebugStrName = AsString(); + cDebug d("cFCOName::cFCOName(cFCOName&,iFCONameInfo*)"); + d.TraceNever(_T("constructing %X:%X %s (refcount=%d)\n"), this, mpPathName, mDebugStrName.c_str(), mpPathName->GetRefCount()); +#endif +} + +cFCOName::~cFCOName() +{ +#ifdef _DEBUG + cDebug d("cFCOName::~cFCOName()"); + d.TraceNever(_T("destructing %X:%X %s (refcount=%d)\n"), this, mpPathName, mDebugStrName.c_str(), mpPathName->GetRefCount()); +#endif + + mpPathName->Release(); +} + +void cFCOName::SetNameInfo(iFCONameInfo* pNI) +{ + if( pNI ) + { + mbCaseSensitive = pNI->IsCaseSensitive(); + mDelimiter = pNI->GetDelimitingChar(); + } + else + { + mbCaseSensitive = iTWFactory::GetInstance()->GetNameInfo()->IsCaseSensitive(); + mDelimiter = iTWFactory::GetInstance()->GetNameInfo()->GetDelimitingChar(); + } +#ifdef _DEBUG + if( mpPathName != NULL ) // this could be called from the constructor before this is initialized. + mDebugStrName = AsString(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::operator = (const cFCOName& rhs) +{ + mpPathName->Release(); + // TODO -- I am sure this won't work (const-ness) + mpPathName = rhs.mpPathName; + mpPathName->AddRef(); + mDelimiter = rhs.mDelimiter; + mbCaseSensitive = rhs.mbCaseSensitive; +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} +void cFCOName::operator = (const TSTRING& rhs) +{ + *this = rhs.c_str(); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} + +void cFCOName::operator = (const TCHAR* rhs) +{ + // if I have the only handle on this vector, I can reuse it + // otherwise, I have to release it. + if(mpPathName->GetRefCount() != 1) + { + mpPathName->Release(); + mpPathName = new cFCOName_i; + } + ParseString(rhs); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// ParseString +// here is how the string is broken down: between every item in +// mpPathName.mNames, there is assumed to be a delimiter. It is assumed there +// is no delimiter at the beginning of the path. If there is, or if +// double delimiters appear anywhere, that is signified by putting an empty +// string into the list. Any delimiter that appears at the end of the string +// is removed (so that /etc/ becomes /etc) +/////////////////////////////////////////////////////////////////////////////// + +#define RADS_NTMBS_VER // Try it out first +#ifndef RADS_NTMBS_VER + +void cFCOName::ParseString(const TCHAR* str) +{ + ASSERT(mpPathName); + mpPathName->ClearList(); + int len = _tcslen(str); + + TSTRING name; + const TCHAR* pEnd = str + len; + const TCHAR* pChar = str; + + // break off the next word to add.. + const TCHAR* pBegin = pChar; + while(pChar < pEnd) + { + while((*pChar != mDelimiter) && (pChar < pEnd)) + pChar++; + // if pChar == pBegin, then we have an extra delimiter; add it. + // TODO -- right now, I will suppress the final delimiter; I don't know if this is the + // right thing to do + if(pChar == pBegin) + { + // NOTE -- there is a special case here -- "/" (the root directory); it will be represented + // as a single empty node. This is handled by the (pChar != str) below. + if((pChar + 1 >= pEnd) && (pChar != str)) + // don't add the trailing slash + break; + name = _T(""); + } + else + name.assign(pBegin, (pChar - pBegin)); + cFCONameTblNode* pNode = cFCOName_i::msNameTbl.CreateNode(name); + mpPathName->mNames.push_back(pNode); + pBegin = ++pChar; + } +} + +#else//RADS_NTMBS_VER + + +void cFCOName::ParseString( const TCHAR* pszin ) +{ + ASSERT( mpPathName != 0); + + mpPathName->ClearList(); + + TSTRING ats = const_cast(pszin + 0); + TSTRING::const_iterator at = ats.begin(); + TSTRING::const_iterator end = at; + while ( *end ) ++end; // NOTE: Find end + + TSTRING::const_iterator beg = at; + while ( at < end ) + { + while ( !(*at == mDelimiter) && at < end ) + at = *at ? at + 1 : at; + + if ( at == beg && (*at ? at + 1 : at) >= end && at != ats.begin() ) + break; + + cFCONameTblNode* pNode = + cFCOName_i::msNameTbl.CreateNode( TSTRING( beg, at ) ); + + mpPathName->mNames.push_back( pNode ); + + beg = ( at = (*at ? at + 1 : at) ); + } +} + +#endif//RADS_NTMBS_VER + +/////////////////////////////////////////////////////////////////////////////// +// AsString +/////////////////////////////////////////////////////////////////////////////// +TSTRING cFCOName::AsString() const +{ + TSTRING str; + str = _T(""); + ASSERT(mpPathName != 0); + + // this kind of stinks, but I have to special case the root dir ("/") + // if I don't, it appears as an empty string + // 15 Oct -- I also had to add a yucky hack for c:\ in windows + // + // 13 Jan 99 mdb -- I have decided that all fconames that are one item long should be + // considered "root items" and should thus be displayed with a trailing delimiting character. + // + if(mpPathName->mNames.size() == 1) + { + str = (*mpPathName->mNames.begin())->GetString(); + str += mDelimiter; + return str; + } + // end ugly root dir hacks ... + + ListType::iterator i = mpPathName->mNames.begin(); + while(i != mpPathName->mNames.end()) + { + // the loop is constructed in this odd fashion because I don't want a trailing mDelimiter + str += (*i)->GetString(); + i++; + if(i != mpPathName->mNames.end()) + str += mDelimiter; + } + + return str; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetShortName +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cFCOName::GetShortName() const +{ + ASSERT( ! mpPathName->mNames.empty() ); + if( mpPathName->mNames.empty() ) + return 0; + + return ( mpPathName->mNames.back()->GetString() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::Clear() +{ + //TODO -- I could probably implement this a little cleaner... + // + while( ! mpPathName->mNames.empty() ) + { + Pop(); + } +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetRelationship +/////////////////////////////////////////////////////////////////////////////// +cFCOName::Relationship cFCOName::GetRelationship(const cFCOName& rhs) const +{ + ListType::iterator myIter, rhsIter; + + // get the easy equality out of the case first... + if(mpPathName == rhs.mpPathName) + return REL_EQUAL; + + // if either name is case sensitive, we will do a case sensitive compare + bool bCaseSensitive = (IsCaseSensitive() || rhs.IsCaseSensitive()); + bool bEqual; + + for(myIter = mpPathName->mNames.begin(), rhsIter = rhs.mpPathName->mNames.begin(); + (myIter != mpPathName->mNames.end() && rhsIter != rhs.mpPathName->mNames.end()); + myIter++, rhsIter++) + { + if(bCaseSensitive) + bEqual = (*myIter == *rhsIter); + else + bEqual = ((*myIter)->GetLowercaseNode() == (*rhsIter)->GetLowercaseNode()); + if(! bEqual) + return REL_UNRELATED; + } + + // if we got this far, one is above another, or they are equal... + if((myIter == mpPathName->mNames.end()) && (rhsIter == rhs.mpPathName->mNames.end())) + return REL_EQUAL; + else if(myIter == mpPathName->mNames.end()) + // I am shorter; I am above rhs + return REL_ABOVE; + else + return REL_BELOW; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Read +// TODO -- serialize the hash table and nodes instead of reading and writing +// as a string +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("FCO Name Read"))); + + TSTRING str; + pSerializer->ReadString(str); + int16 dummy = 0; + + // serialize the delimiter +#ifdef _UNICODE + pSerializer->ReadInt16( (int16&)mDelimiter ); +#else + pSerializer->ReadInt16( dummy ); + const wchar_t wc = dummy; + size_t N = ::wcstombs( &mDelimiter, &wc, 1 ); + if ( N == (size_t)-1 ) + throw eCharacterEncoding(); +#endif + + // read the case-sensitiveness + pSerializer->ReadInt16(dummy); + if(dummy == 0) + mbCaseSensitive = false; + else + mbCaseSensitive = true; + + ParseString(str.c_str()); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +// TODO -- serialize the hash table and nodes instead of reading and writing +// as a string +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteString(AsString()); + + // serialize the delimiter +#ifdef _UNICODE + pSerializer->WriteInt16(mDelimiter); +#else + wchar_t wc; + mbtowc(&wc, &mDelimiter, 1); + pSerializer->WriteInt16(wc); +#endif + + pSerializer->WriteInt16( mbCaseSensitive ? (int16)1 : (int16)0); +} + +/////////////////////////////////////////////////////////////////////////////// +// CopyOnModify -- if the refrence count on mpPathName is > 1, release it and +// allocate our own copy of it +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::CopyOnModify() +{ + if(mpPathName->GetRefCount() > 1) + { + cFCOName_i* pOld= mpPathName; + mpPathName = new cFCOName_i; + ListType::iterator i; + for(i = pOld->mNames.begin(); i != pOld->mNames.end(); ++i) + { + (*i)->AddRef(); + mpPathName->mNames.push_back(*i); + } + pOld->Release(); + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// Push +/////////////////////////////////////////////////////////////////////////////// +void cFCOName::Push(const TSTRING& str) +{ + // we must copy the fconame if there is more than one refrence to it... + CopyOnModify(); + + cFCONameTblNode* pNode = cFCOName_i::msNameTbl.CreateNode(str); + mpPathName->mNames.push_back(pNode); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// Pop +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cFCOName::Pop() +{ + // we must copy the fconame if there is more than one refrence to it... + CopyOnModify(); + + ASSERT(GetSize() > 0); + + cFCONameTblNode* pNode = mpPathName->mNames.back(); + mpPathName->mNames.pop_back(); + + // I do this assertion because it should also be in the hash table + ASSERT(pNode->GetRefCount() > 1); + const TCHAR* ret = pNode->GetString(); + pNode->Release(); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// PopFront +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cFCOName::PopFront() +{ + // we must copy the fconame if there is more than one reference to it... + CopyOnModify(); + + ASSERT(GetSize() > 0); + + cFCONameTblNode* pNode = mpPathName->mNames.front(); + cFCOName::ListType::iterator i = mpPathName->mNames.begin(); + mpPathName->mNames.erase( i ); + + // I do this assertion because it should also be in the hash table + ASSERT(pNode->GetRefCount() > 1); + const TCHAR* ret = pNode->GetString(); + pNode->Release(); +#ifdef _DEBUG + mDebugStrName = AsString(); +#endif + return ret; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetSize +/////////////////////////////////////////////////////////////////////////////// +int cFCOName::GetSize() const +{ + return mpPathName->mNames.size(); +} + +/////////////////////////////////////////////////////////////////////////////// +// operator< -- provides an arbitrary ordering to cFCONames. The algorithm I chose +// is like strcmp, except instead of comparing characters, I compare +// cFCONameTblNode* addresses +/////////////////////////////////////////////////////////////////////////////// +bool cFCOName::operator<(const cFCOName& rhs) const +{ + ListType::iterator myIter, rhsIter; + + // if either name is case sensitive, we will do a case sensitive compare + bool bCaseSensitive = (IsCaseSensitive() || rhs.IsCaseSensitive()); + + // get the easy equality out of the case first... + if(mpPathName == rhs.mpPathName) + return false; + + for(myIter = mpPathName->mNames.begin(), rhsIter = rhs.mpPathName->mNames.begin(); + (myIter != mpPathName->mNames.end() && rhsIter != rhs.mpPathName->mNames.end()); + myIter++, rhsIter++) + { + if(bCaseSensitive) + { + if (*myIter > *rhsIter) + return false; + else if (*myIter < *rhsIter) + return true; + } + else + { + // not case sensitive + if ((*myIter)->GetLowercaseNode() > (*rhsIter)->GetLowercaseNode()) + return false; + else if ((*myIter)->GetLowercaseNode() < (*rhsIter)->GetLowercaseNode()) + return true; + } + // if they are equal, keep going + } + + // if we got this far, one is above another, or they are equal... + if(rhsIter == rhs.mpPathName->mNames.end()) + // either I am longer of we are equal; so return false + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// cFCONameIter +//----------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////////////////// +// cFCONameIter +/////////////////////////////////////////////////////////////////////////////// +cFCONameIter::cFCONameIter(const cFCOName& name) +: mName(name) +{ + SeekBegin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ~cFCONameIter +/////////////////////////////////////////////////////////////////////////////// +cFCONameIter::~cFCONameIter() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSize +/////////////////////////////////////////////////////////////////////////////// +int cFCONameIter::GetSize() const +{ + return mName.mpPathName->mNames.size(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekBegin +/////////////////////////////////////////////////////////////////////////////// +void cFCONameIter::SeekBegin() +{ + mIter = mName.mpPathName->mNames.begin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Next +/////////////////////////////////////////////////////////////////////////////// +void cFCONameIter::Next() +{ + mIter++; +} + +/////////////////////////////////////////////////////////////////////////////// +// Done +/////////////////////////////////////////////////////////////////////////////// +bool cFCONameIter::Done() const +{ + return ( mIter == mName.mpPathName->mNames.end() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetName +/////////////////////////////////////////////////////////////////////////////// +const TCHAR* cFCONameIter::GetName() const +{ + ASSERT( ! Done() ); + + return (*mIter)->GetString(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Prev +/////////////////////////////////////////////////////////////////////////////// +void cFCONameIter::Prev() +{ + mIter--; +} + +/////////////////////////////////////////////////////////////////////////////// +// Index +/////////////////////////////////////////////////////////////////////////////// +int cFCONameIter::Index() const +{ + ASSERT( ! Done() ); + return ( mIter - mName.mpPathName->mNames.begin() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekTo +/////////////////////////////////////////////////////////////////////////////// +void cFCONameIter::SeekTo( int index ) +{ + ASSERT( (index >= 0) && (index < mName.GetSize()) ); + + mIter = ( mName.mpPathName->mNames.begin() + index ); +} + + diff --git a/src/fco/fconame.h b/src/fco/fconame.h new file mode 100644 index 0000000..3c7966a --- /dev/null +++ b/src/fco/fconame.h @@ -0,0 +1,232 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconame.h +// +// cFCOName -- represents the name of an FCO +#ifndef __FCONAME_H +#define __FCONAME_H + +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif +#ifndef __FCONAMEINFO_H +#include "fconameinfo.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOName -- How we name a FCO. The implementation has ended up being +// a wrapper around a standard string. +/////////////////////////////////////////////////////////////////////////////// +class cFCONameTblNode; +class cFCONameIter; +class cFCOName_i; + +class cFCOName : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + typedef cFCONameIter iterator; + + cFCOName(iFCONameInfo* iNI = NULL); + cFCOName(const cFCOName& rhs); + + explicit cFCOName(const TSTRING& rhs, iFCONameInfo* iNI = NULL); + explicit cFCOName(const TCHAR* rhs, iFCONameInfo* iNI = NULL); + // these ctors are explicit because it is expensive to create these things, so we don't want to + // do it unexpectedly + virtual ~cFCOName(); + + void operator = (const cFCOName& rhs); + void operator = (const TSTRING& rhs); + void operator = (const TCHAR* rhs); + + bool operator < (const cFCOName& rhs) const; + // defines an arbitrary order for cFCONames. This is so that names can + // be stored in trees and other ordered data structures in order to facilitate + // fast lookups. + + bool operator == (const cFCOName& rhs) const; + bool operator != (const cFCOName& rhs) const; + bool IsEqual (const cFCOName& rhs) const; + // both of these are synonyms for (GetRelationship(rhs) == REL_EQUAL) + + TSTRING AsString() const; + // return a string representation of the string + + bool IsCaseSensitive() const; + void SetCaseSensitive(bool val); + // determines how name comparisons are done. If two cFCONames are compared who are + // both case insensitive, a case insensitive compare is done. If both are case sensitive, + // a case sensitive compare is done. If one is and one isn't case sensitive (? TODO: what + // is the right thing to do in this case? ASSERT(0)? do a case sensitive compare??) + TCHAR GetDelimiter() const; + void SetDelimiter(TCHAR delimiter); + // defines what the path-delimiting character is + + void Push(const TSTRING& str); + // pushes the named string onto the end of the path. A delimiter is implicitely placed between the old end + // and the new string. if debug is defined, it is asserted that the new string does not contain the + // delimiting character + const TCHAR* Pop(); + // removes the last part of the path from the name and returns it. ASSERTS and returns an undefined value if + // the path is empty + const TCHAR* PopFront(); + // removes the first part of the path from the name and returns it. ASSERTS and returns an undefined value if + // the path is empty + void Clear(); + // removes all elements from the name; after this, GetSize() == 0. + const TCHAR* GetShortName() const; + // this will return the final string in the vector. It will assert that the name is not empty. + int GetSize() const; + // returns the number of path items (strings between delimiters) that are in the fco name. It is always equal + // to the number of delimiters in the path plus one. + + enum Relationship + { + REL_BELOW, // an fco is below another (/etc/passwd is below /etc) + REL_ABOVE, // an fco is above another (/etc is above /etc/passwd) + REL_EQUAL, // the fcos are equal (/etc/passwd is equal to /etc/passwd) + REL_UNRELATED // the fcos are unrelated (/var/spool/mail is unrelated to /var/log/pig.log) + }; + Relationship GetRelationship(const cFCOName& rhs) const; + // returns the relationship of _this_ name to the one passed in (ie -- if REL_BELOW is returned, + // this fco name is below the one passed in) + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + ////////////////////////////////// + // Debugging method + ////////////////////////////////// + static void ClearNameTable(); + // this method should _only_ be called when the program is exiting, and you are positively sure you + // will not be using or creating any more cFCONames. Violating this rule will result in unpredictable + // results. This clears out the cFCOName internal name table, making memory leaks easier to find. +protected: + friend class cFCOName_i; + friend class cFCONameIter; + + void ParseString(const TCHAR* str); + // helper function that takes the pathname pointer to by str and fills out mpPathName + void CopyOnModify(); + // if the fconame is modified and mpPathName is shared by more than one object, this will + // release mpPathName and create a new one, so we don't change any other object's data + void SetNameInfo(iFCONameInfo* pNI); + // sets the delimiter and case sensitiveness to the name info's + + cFCOName_i* mpPathName; + TCHAR mDelimiter; // the delimiting character in names (ie -- in file systems, it is '/') + bool mbCaseSensitive; // determines whether name compares are case sensitive of not + + // this is what type of structure holds the elements of the name + // + typedef std::vector ListType; + +#ifdef _DEBUG + TSTRING mDebugStrName; // so we can see this guy's value in the debug window +#endif +}; + +//----------------------------------------------------------------------------- +// cFCONameIter +//----------------------------------------------------------------------------- +class cFCONameIter_i; +class cFCONameIter +{ +public: + cFCONameIter(const cFCOName& name); + ~cFCONameIter(); + + int GetSize() const; // returns the number of entries in the fco name + void SeekBegin(); + void Next(); + void Prev(); + bool Done() const; + + int Index() const; + // return the current offset from the beginning of the short name list + void SeekTo( int index ); + // seeks to the given index. asserts that the index is appropriate for the + // current fco name. + + const TCHAR* GetName() const; +private: + void operator=(const cFCONameIter& rhs); // not impl + cFCONameIter(const cFCONameIter& rhs); // not impl + + // the data... + // + const cFCOName& mName; + cFCOName::ListType::const_iterator mIter; +}; + +//############################################################################# +// inline implementation +inline bool cFCOName::IsCaseSensitive() const +{ + return mbCaseSensitive; +} +inline void cFCOName::SetCaseSensitive(bool val) +{ + mbCaseSensitive = val; +} +inline TCHAR cFCOName::GetDelimiter() const +{ + return mDelimiter; +} +inline void cFCOName::SetDelimiter(TCHAR delimiter) +{ + mDelimiter = delimiter; +} + +/////////////////////////////////////////////////////////////////////////////// +// IsEqual +/////////////////////////////////////////////////////////////////////////////// +inline bool cFCOName::IsEqual(const cFCOName& rhs) const +{ + return (GetRelationship(rhs) == cFCOName::REL_EQUAL); +} + +inline bool cFCOName::operator==(const cFCOName& rhs) const +{ + return IsEqual(rhs); +} +inline bool cFCOName::operator!=(const cFCOName& rhs) const +{ + return (! IsEqual(rhs)); +} + + +#endif //__FCONAME_H + diff --git a/src/fco/fconame.h~ b/src/fco/fconame.h~ new file mode 100644 index 0000000..3e07ad0 --- /dev/null +++ b/src/fco/fconame.h~ @@ -0,0 +1,231 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconame.h +// +// cFCOName -- represents the name of an FCO +#ifndef __FCONAME_H +#define __FCONAME_H + +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif +#ifndef __FCONAMEINFO_H +#include "fconameinfo.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOName -- How we name a FCO. The implementation has ended up being +// a wrapper around a standard string. +/////////////////////////////////////////////////////////////////////////////// +class cFCONameTblNode; +class cFCONameIter; + +class cFCOName : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + typedef cFCONameIter iterator; + + cFCOName(iFCONameInfo* iNI = NULL); + cFCOName(const cFCOName& rhs); + + explicit cFCOName(const TSTRING& rhs, iFCONameInfo* iNI = NULL); + explicit cFCOName(const TCHAR* rhs, iFCONameInfo* iNI = NULL); + // these ctors are explicit because it is expensive to create these things, so we don't want to + // do it unexpectedly + virtual ~cFCOName(); + + void operator = (const cFCOName& rhs); + void operator = (const TSTRING& rhs); + void operator = (const TCHAR* rhs); + + bool operator < (const cFCOName& rhs) const; + // defines an arbitrary order for cFCONames. This is so that names can + // be stored in trees and other ordered data structures in order to facilitate + // fast lookups. + + bool operator == (const cFCOName& rhs) const; + bool operator != (const cFCOName& rhs) const; + bool IsEqual (const cFCOName& rhs) const; + // both of these are synonyms for (GetRelationship(rhs) == REL_EQUAL) + + TSTRING AsString() const; + // return a string representation of the string + + bool IsCaseSensitive() const; + void SetCaseSensitive(bool val); + // determines how name comparisons are done. If two cFCONames are compared who are + // both case insensitive, a case insensitive compare is done. If both are case sensitive, + // a case sensitive compare is done. If one is and one isn't case sensitive (? TODO: what + // is the right thing to do in this case? ASSERT(0)? do a case sensitive compare??) + TCHAR GetDelimiter() const; + void SetDelimiter(TCHAR delimiter); + // defines what the path-delimiting character is + + void Push(const TSTRING& str); + // pushes the named string onto the end of the path. A delimiter is implicitely placed between the old end + // and the new string. if debug is defined, it is asserted that the new string does not contain the + // delimiting character + const TCHAR* Pop(); + // removes the last part of the path from the name and returns it. ASSERTS and returns an undefined value if + // the path is empty + const TCHAR* PopFront(); + // removes the first part of the path from the name and returns it. ASSERTS and returns an undefined value if + // the path is empty + void Clear(); + // removes all elements from the name; after this, GetSize() == 0. + const TCHAR* GetShortName() const; + // this will return the final string in the vector. It will assert that the name is not empty. + int GetSize() const; + // returns the number of path items (strings between delimiters) that are in the fco name. It is always equal + // to the number of delimiters in the path plus one. + + enum Relationship + { + REL_BELOW, // an fco is below another (/etc/passwd is below /etc) + REL_ABOVE, // an fco is above another (/etc is above /etc/passwd) + REL_EQUAL, // the fcos are equal (/etc/passwd is equal to /etc/passwd) + REL_UNRELATED // the fcos are unrelated (/var/spool/mail is unrelated to /var/log/pig.log) + }; + Relationship GetRelationship(const cFCOName& rhs) const; + // returns the relationship of _this_ name to the one passed in (ie -- if REL_BELOW is returned, + // this fco name is below the one passed in) + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + ////////////////////////////////// + // Debugging method + ////////////////////////////////// + static void ClearNameTable(); + // this method should _only_ be called when the program is exiting, and you are positively sure you + // will not be using or creating any more cFCONames. Violating this rule will result in unpredictable + // results. This clears out the cFCOName internal name table, making memory leaks easier to find. +protected: + friend class cFCOName_i; + friend class cFCONameIter; + + void ParseString(const TCHAR* str); + // helper function that takes the pathname pointer to by str and fills out mpPathName + void CopyOnModify(); + // if the fconame is modified and mpPathName is shared by more than one object, this will + // release mpPathName and create a new one, so we don't change any other object's data + void SetNameInfo(iFCONameInfo* pNI); + // sets the delimiter and case sensitiveness to the name info's + + cFCOName_i* mpPathName; + TCHAR mDelimiter; // the delimiting character in names (ie -- in file systems, it is '/') + bool mbCaseSensitive; // determines whether name compares are case sensitive of not + + // this is what type of structure holds the elements of the name + // + typedef std::vector ListType; + +#ifdef _DEBUG + TSTRING mDebugStrName; // so we can see this guy's value in the debug window +#endif +}; + +//----------------------------------------------------------------------------- +// cFCONameIter +//----------------------------------------------------------------------------- +class cFCONameIter_i; +class cFCONameIter +{ +public: + cFCONameIter(const cFCOName& name); + ~cFCONameIter(); + + int GetSize() const; // returns the number of entries in the fco name + void SeekBegin(); + void Next(); + void Prev(); + bool Done() const; + + int Index() const; + // return the current offset from the beginning of the short name list + void SeekTo( int index ); + // seeks to the given index. asserts that the index is appropriate for the + // current fco name. + + const TCHAR* GetName() const; +private: + void operator=(const cFCONameIter& rhs); // not impl + cFCONameIter(const cFCONameIter& rhs); // not impl + + // the data... + // + const cFCOName& mName; + cFCOName::ListType::const_iterator mIter; +}; + +//############################################################################# +// inline implementation +inline bool cFCOName::IsCaseSensitive() const +{ + return mbCaseSensitive; +} +inline void cFCOName::SetCaseSensitive(bool val) +{ + mbCaseSensitive = val; +} +inline TCHAR cFCOName::GetDelimiter() const +{ + return mDelimiter; +} +inline void cFCOName::SetDelimiter(TCHAR delimiter) +{ + mDelimiter = delimiter; +} + +/////////////////////////////////////////////////////////////////////////////// +// IsEqual +/////////////////////////////////////////////////////////////////////////////// +inline bool cFCOName::IsEqual(const cFCOName& rhs) const +{ + return (GetRelationship(rhs) == cFCOName::REL_EQUAL); +} + +inline bool cFCOName::operator==(const cFCOName& rhs) const +{ + return IsEqual(rhs); +} +inline bool cFCOName::operator!=(const cFCOName& rhs) const +{ + return (! IsEqual(rhs)); +} + + +#endif //__FCONAME_H + diff --git a/src/fco/fconame_t.cpp b/src/fco/fconame_t.cpp new file mode 100644 index 0000000..02c0504 --- /dev/null +++ b/src/fco/fconame_t.cpp @@ -0,0 +1,141 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconame_t.cpp +/////////////////////////////////////////////////////////////////////////////// + +#include "stdfco.h" + +#include "fconame.h" + +#include "test/test.h" +#include "core/serializer.h" +#include "core/serializerimpl.h" +#include "core/archive.h" +#include "genreswitcher.h" + +void TestFCOName() +{ +#if 0 + // the following only works w/case insensitive names + cGenreSwitcher::GetInstance()->SelectGenre( cGenre::NTFS ); +#endif + + // test the relationship operator... + cFCOName above (_T("/etc")); + cFCOName extraDel (_T("/etc/")); + cFCOName below (_T("/etc/passwd")); + cFCOName same (_T("/etc/passwd")); + cFCOName unrel (_T("/var/spool/mail")); + cFCOName caseTest (_T("/etc/PASsWD")); + cFCOName caseTest2 (_T("/etc/passwd/dog")); + cFCOName test (_T("/etcc")); + + TEST(above.GetRelationship(below) == cFCOName::REL_ABOVE); + TEST(below.GetRelationship(above) == cFCOName::REL_BELOW); + TEST(below.GetRelationship(same) == cFCOName::REL_EQUAL); + TEST(unrel.GetRelationship(above) == cFCOName::REL_UNRELATED); + TEST(test.GetRelationship(above) == cFCOName::REL_UNRELATED); + TEST(caseTest.GetRelationship(same) == cFCOName::REL_UNRELATED); + // test the extra delimiter removal... + caseTest.SetCaseSensitive(false); + caseTest2.SetCaseSensitive(false); + same.SetCaseSensitive(false); + above.SetCaseSensitive(false); + TEST(caseTest.GetRelationship(caseTest2) == cFCOName::REL_ABOVE); + TEST(caseTest.GetRelationship(same) == cFCOName::REL_EQUAL); + + // test push() and pop() + cFCOName dog(_T("/a/brown/dog")); + cFCOName cat(_T("/a/brown/cat")); + TEST(dog.GetSize() == 4); + dog.Push(_T("woof")); + TEST(dog.AsString().compare(_T("/a/brown/dog/woof")) == 0); + TEST(dog.GetSize() == 5); + TEST(_tcscmp(dog.Pop(),_T("woof")) == 0); + TEST(_tcscmp(dog.Pop(),_T("dog")) == 0); + TEST(cat.GetRelationship(dog) == cFCOName::REL_BELOW); + TEST(_tcscmp(cat.Pop(),_T("cat")) == 0); + TEST(dog.AsString().compare(cat.AsString()) == 0); + TEST(dog.GetRelationship(cat) == cFCOName::REL_EQUAL); + + cFCOName nullName; + TEST(*nullName.AsString().c_str() == 0); + + cFCOName charName(_T("/a/character/name")); + TEST(_tcscmp(charName.AsString().c_str(), _T("/a/character/name")) == 0); + + cFCOName stringName(_T("/a/string/name")); + TEST(_tcscmp(stringName.AsString().c_str(), _T("/a/string/name")) == 0); + + cFCOName dosName(_T("c:/a/dos/name")); + TEST(_tcscmp(dosName.AsString().c_str(), _T("c:/a/dos/name")) == 0); + + cFCOName copyName(stringName); + TEST(_tcscmp(copyName.AsString().c_str(), _T("/a/string/name")) == 0); + + cFCOName name(_T("new name")); + nullName = name; + TEST(_tcscmp(nullName.AsString().c_str(), _T("new name")) == 0); + + nullName = _T("newer name"); + TEST(_tcscmp(nullName.AsString().c_str(), _T("newer name")) == 0); + + cMemoryArchive memArc; + { + cSerializerImpl ser(memArc, cSerializerImpl::S_WRITE); + ser.Init(); + ser.WriteObject(&charName); + stringName.SetDelimiter(_T('\\')); + ser.WriteObject(&stringName); + ser.Finit(); + } + memArc.Seek(0, cBidirArchive::BEGINNING); + { + cSerializerImpl ser(memArc, cSerializerImpl::S_READ); + cFCOName name1, name2; + ser.Init(); + ser.ReadObject(&name1); + ser.ReadObject(&name2); + ser.Finit(); + + TEST(name1.IsEqual(charName)); + TEST(name2.IsEqual(stringName)); + TEST(! name1.IsCaseSensitive()); + TEST(! name2.IsCaseSensitive()); + TEST(name2.GetDelimiter() == _T('\\')); + TEST(name1.GetDelimiter() == _T('/')); + } + +} + + diff --git a/src/fco/fconameinfo.h b/src/fco/fconameinfo.h new file mode 100644 index 0000000..efee64a --- /dev/null +++ b/src/fco/fconameinfo.h @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconameinfo.h +// +#ifndef __FCONAMEINFO_H +#define __FCONAMEINFO_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//----------------------------------------------------------------------------- +// iFCONameInfo +//----------------------------------------------------------------------------- +class iFCONameInfo +{ +public: + virtual bool IsCaseSensitive() const = 0; + virtual TCHAR GetDelimitingChar() const = 0; +}; + + +#endif + diff --git a/src/fco/fconametbl.cpp b/src/fco/fconametbl.cpp new file mode 100644 index 0000000..d534d95 --- /dev/null +++ b/src/fco/fconametbl.cpp @@ -0,0 +1,224 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconametbl.cpp +// + +#include "stdfco.h" +#include "fconametbl.h" + +//############################################################################# +// cFCONameTblNode +//############################################################################# +// uncomment this to allocate fconametblnodes from a pool. +//cObjectPoolBase cFCONameTblNode::msAllocator(sizeof(cFCONameTblNode), 1000); + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// grow heap for allocating strings +// uncomment this stuff to use the grow heap... +// + +#include "core/growheap.h" + +// TODO:BAM -- maybe make a PAGE_SIZE in platform.h +enum +{ + FCONAME_HEAP_INITIAL_SIZE = 0x1000, // 4k + FCONAME_HEAP_GROW_BY = 0x1000 +}; + +static cGrowHeap gFCONameHeap( FCONAME_HEAP_INITIAL_SIZE, FCONAME_HEAP_GROW_BY, _T("FCO Name") ); + +inline void* util_AllocMem(int size) +{ + return gFCONameHeap.Malloc( size ); +} +inline void util_FreeMem(void* pData) +{ + +} + +// +// ...and uncomment this to do allocing the normal way... +// +/* +inline void* util_AllocMem(int size) +{ + return malloc( size ); +} +inline void util_FreeMem(void* pData) +{ + free(pData); +} +*/ + +// +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +void cFCONameTblNode::SetLowercaseNode(cFCONameTblNode* pNewNode) +{ + ASSERT(pNewNode != 0); // doesn't make sense to set this to NULL + + if(mpLowerNode) + mpLowerNode->Release(); + if(pNewNode == this) + { + // we can't store a pointer to ourselves, since reference counting doesn't go well + // with circular pointers, so we will represent this with a NULL pointer + mpLowerNode = NULL; + return; + } + pNewNode->AddRef(); + mpLowerNode = pNewNode; +} + +void cFCONameTblNode::SetString(const TSTRING& newStr) +{ + if( mpString != NULL ) + { + delete [] mpString; + mpString = NULL; + } + + mpString = (TCHAR*)util_AllocMem( sizeof(TCHAR)*(newStr.length()+1) ); + _tcscpy( mpString, newStr.c_str() ); + + // NOTE -- the lower case pointer is now invalid. +} + +cFCONameTblNode::cFCONameTblNode(const TSTRING& name, const cFCONameTblNode* node) : + mpString(NULL), + mpLowerNode(node) +{ + SetString( name ); +} + +cFCONameTblNode::~cFCONameTblNode() +{ + if(mpLowerNode) + mpLowerNode->Release(); + if(mpString != NULL) + { + util_FreeMem( mpString ); + mpString = NULL; + } +} + +void cFCONameTblNode::Delete() const +{ + ((cFCONameTblNode*)this)->~cFCONameTblNode(); + util_FreeMem((void*)this); +} + + +//############################################################################# +// cFCONameTbl +//############################################################################# + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cFCONameTbl::cFCONameTbl(int defSize) : + mTable(defSize) +{ +} + +cFCONameTbl::~cFCONameTbl() +{ +#ifdef _DEBUG + cDebug d("cFCONameTbl::~cFCONameTbl()"); + d.TraceDebug("Tracing cFCONameTblNode hash table statistics:\n"); + mTable.TraceDiagnostics(); +#endif + Clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateNode +/////////////////////////////////////////////////////////////////////////////// + +cFCONameTblNode* cFCONameTbl::CreateNode(const TSTRING& nodeName) +{ + cFCONameTblNode* pNode, *pLowerNode; + if(mTable.Lookup(nodeName.c_str(), pNode)) + { + // this already exists in the table; just return the existing node + pNode->AddRef(); + return pNode; + } + pNode = new(util_AllocMem(sizeof(cFCONameTblNode))) cFCONameTblNode(nodeName, NULL); + mTable.Insert(pNode->GetString(), pNode); + + // fill out the lower-case info + TSTRING lowStr = pNode->GetString(); + TSTRING::iterator i; + + // TODO:BAM -- does this have any meaning in mb? + for(i = lowStr.begin(); i != lowStr.end(); ++i) + { + *i = _totlower(*i); + } + // see if this exists in the table (it could potentially look up itself!) + if(mTable.Lookup(lowStr.c_str(), pLowerNode)) + { + pNode->SetLowercaseNode(pLowerNode); + } + else + { + // we know that the original string is not lower case if we got to this point + pLowerNode = new(util_AllocMem(sizeof(cFCONameTblNode))) cFCONameTblNode(lowStr, NULL); + pLowerNode->SetLowercaseNode(pLowerNode); + pNode->SetLowercaseNode(pLowerNode); + mTable.Insert(pLowerNode->GetString(), pLowerNode); + } + + pNode->AddRef(); + return pNode; +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear +/////////////////////////////////////////////////////////////////////////////// +void cFCONameTbl::Clear() +{ + cHashTableIter iter(mTable); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + iter.Val()->Release(); + } + + mTable.Clear(); +} + diff --git a/src/fco/fconametbl.h b/src/fco/fconametbl.h new file mode 100644 index 0000000..4369668 --- /dev/null +++ b/src/fco/fconametbl.h @@ -0,0 +1,184 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconametbl.h +// +// cFCONameTbl -- a hash table used in the implementation of cFCOName +#ifndef __FCONAMETBL_H +#define __FCONAMETBL_H + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +#ifndef __REFCOUNTOBJ_H +#include "core/refcountobj.h" +#endif +#ifndef __HASHTABLE_H +#include "core/hashtable.h" +#endif + +// uncomment this to allocate fconametblnodes from a pool. +/* +#ifndef __OBJECTPOOL_H +#include "objectpool.h" +#endif +*/ +// end TODO + + +class cFCONameTbl_i; + +/////////////////////////////////////////////////////////////////////////////// +// cFCONameTblNode -- a node in the cFCONameTbl, this class has the following +// properties: +// (1) it is reference counted, so ambiguity over who owns it doesn't exist +// (2) it keeps track of a case-sensitive character string +// (3) it keeps a pointer to another cFCONameTblNode that is the lower-case +// version of the node (if the node is totally lower case, then mpLowerNode +// is NULL, but GetLowercaseNode() still returns a valid pointer) +// TODO -- make this serializable +/////////////////////////////////////////////////////////////////////////////// +class cFCONameTblNode : public cRefCountObj +{ +friend class cFCONameTbl; +public: + bool operator== (const cFCONameTblNode& rhs) const; + bool operator!= (const cFCONameTblNode& rhs) const; + // for efficency, op== is defined as (this == &rhs) + + const cFCONameTblNode* GetLowercaseNode() const; + void SetLowercaseNode(cFCONameTblNode* pNewNode); + // gets and sets the lowercase node pointer. Might point to itself if the string + // this node contains is totally lower case. + + TCHAR* GetString() const; + // gets the string associated with this node + void SetString(const TSTRING& newStr); + // sets the string associated with this node + // TODO -- this is a very dangerous operation to do; do we ever want the client + // to be able to do this (that is, should this method exist)? + + // uncomment to allocate these from a pool + // static cObjectPoolBase msAllocator; + // void* operator new(size_t) { return msAllocator.Alloc(); } + // void operator delete(void* addr) { msAllocator.Free(addr); } + +protected: + // these are protected to keep the client from creating nodes on the stack + // or delete()ing them. + cFCONameTblNode(const TSTRING& name, const cFCONameTblNode* node); + ~cFCONameTblNode(); + virtual void Delete() const; + // overridden from cRefCountObj; this is done so that if we are alloced + // from a memory pool, we can be deleted appropriately. +private: + cFCONameTblNode(const cFCONameTblNode& rhs); // not impl + cFCONameTblNode& operator= (const cFCONameTblNode& rhs);// not impl + + TCHAR* mpString; + const cFCONameTblNode* mpLowerNode; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCONameTbl -- keeps a hash table of cFCONameTblNodes. This class does the following: +// (1) serves as a factory for cFCONameTableNodes, returning objects that have +// properly filled out mpLowerNode fields +// (2) Keeps track of all nodes created; two successive calls to create "aBc" will +// return the same pointer; a call to create "abc" will return a pointer to the +// Node("aBc")->GetLowercaseNode() +/////////////////////////////////////////////////////////////////////////////// +class cFCONameTbl +{ +public: + cFCONameTbl(int defSize = HASH_VERY_LARGE); + // defSize is the initial hash table size + ~cFCONameTbl(); + + cFCONameTblNode* CreateNode(const TSTRING& nodeName); + // if the named node already exists in the table, it returns a pointer to the + // existing node; otherwise, it creates the node and its lower case representation, + // (if the lowercase node doesn't already exist),adds them to the table + // and returns a pointer to them. The returned object has been AddRef()ed + + void Clear(); + // clears out all the entries in the table + + /////////////////////////////////////////////////////////////////////////////// + // cCharCmp -- class used with the hash table that does a string compare + // of two TCHAR*s to determine equality + class cCharCmp + { + public: + bool operator()(const TCHAR* lhs, const TCHAR* rhs) + { + return (_tcscmp(lhs,rhs) == 0); + } + }; +private: + // TODO -- it is not evident what type the KEY_TYPE should be for the hash tbl; if it is + // a string, we will be storing two copies of all the strings! If it is a const TCHAR*, then + // the equality operator won't work (maybe we should template the hash table with the operators + // needed for the hash as well) + cHashTable mTable; +}; + +//############################################################################# +// inline implementation +//############################################################################# + +//////////////////////// +// cFCONameTblNode +//////////////////////// +inline bool cFCONameTblNode::operator== (const cFCONameTblNode& rhs) const +{ + return (this == &rhs); +} +inline bool cFCONameTblNode::operator!= (const cFCONameTblNode& rhs) const +{ + return (this != &rhs); +} +inline const cFCONameTblNode* cFCONameTblNode::GetLowercaseNode() const +{ + // if mpLowerNode == NULL, then we assume that we are the lowercase node. + if(! mpLowerNode) + return this; + return mpLowerNode; +} + +inline TCHAR* cFCONameTblNode::GetString() const +{ + return mpString; +} + + +#endif + diff --git a/src/fco/fconametbl_t.cpp b/src/fco/fconametbl_t.cpp new file mode 100644 index 0000000..46f374f --- /dev/null +++ b/src/fco/fconametbl_t.cpp @@ -0,0 +1,63 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fconametbl_t.cpp +#include "stdfco.h" +#include "fconametbl.h" +#include "test/test.h" + +void TestFCONameTbl() +{ + cDebug d("TestFCONameTbl()"); + + cFCONameTbl nameTbl; + + cFCONameTblNode* pNode1 = nameTbl.CreateNode(_T("aBc")); + cFCONameTblNode* pNode2 = nameTbl.CreateNode(_T("Abc")); + cFCONameTblNode* pNode3 = nameTbl.CreateNode(_T("abc")); + cFCONameTblNode* pNode4 = nameTbl.CreateNode(_T("def")); + cFCONameTblNode* pNode5 = nameTbl.CreateNode(_T("dEf")); + + TEST(*pNode1 != *pNode2); + TEST(*pNode5 != *pNode4); + TEST(*pNode1->GetLowercaseNode() == *pNode3); + TEST(*pNode2->GetLowercaseNode() == *pNode3); + TEST(*pNode3->GetLowercaseNode() == *pNode3); + TEST(*pNode4->GetLowercaseNode() == *pNode4); + TEST(*pNode5->GetLowercaseNode() == *pNode4); + + + pNode1->Release(); + pNode2->Release(); + pNode3->Release(); + pNode4->Release(); + pNode5->Release(); +} diff --git a/src/fco/fconametranslator.h b/src/fco/fconametranslator.h new file mode 100644 index 0000000..2e01c32 --- /dev/null +++ b/src/fco/fconametranslator.h @@ -0,0 +1,88 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fconametranslator.h +// + +#ifndef __FCONAMETRANSLATOR_H +#define __FCONAMETRANSLATOR_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class cFCOName; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +class iFCONameTranslator +{ +public: + // + // basic functionality + // + virtual TSTRING ToStringRaw( const cFCOName& name ) const = 0; + // provides a "raw" representation of the fco name as a string. This uses only the + // information contained in the cFCOName to construct the string (ie -- no genre specific + // info) + + virtual TSTRING ToStringAPI( const cFCOName& name ) const = 0; + // returns a string representation of the name that can be passed to system API calls. Note + // that this is not possible to do in all genres ( for example, the NT registry ) + + virtual TSTRING ToStringDisplay( const cFCOName& name, bool bUnique = false ) const = 0; + // this function converts an fconame into a string suitable for printing to user. + // Every character in the string will be able to be converted to a multi-byte character + // + // If unique is set, the string will also have the following attributes: + // The returned string will have leading and trailing quotes. + // The string returned must be able to be unambiguously translatable back into an FCO name + // equal to the one that created the string. To use mathematical language, the function that + // maps cFCONames to TSTRINGS must be "one to one" and "onto". + + virtual bool DisplayStringToFCOName( const TSTRING& str, cFCOName& name ) const = 0; + // this function converts strings from FCONameToDisplayString back into an fconame + // returns false if can't convert. +}; + +#endif //__FCONAMETRANSLATOR_H + diff --git a/src/fco/fconametranslator_t.cpp b/src/fco/fconametranslator_t.cpp new file mode 100644 index 0000000..aaea15d --- /dev/null +++ b/src/fco/fconametranslator_t.cpp @@ -0,0 +1,117 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fconametranslator_t.cpp +// Date....: 08/3/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdfco.h" +#include "fconametranslator.h" +#include "genreswitcher.h" +#include "fconame.h" + + +void TestName( const TCHAR* pchName, const TCHAR* pchGenre ); +void TestUnprintable( const TCHAR* pchName, const TCHAR* pchGenre ); + + +void TestFCONameTranslator() +{ + TestName( _T("/not_quoted/tmp"), _T("FS") ); + TestName( _T("/\"quoted\"/tmp"), _T("FS") ); + TestName( _T("/tmp/\"freak\x08y\""), _T("FS") ); + TestUnprintable( _T("c:\\\"more freak\xFFy\""), _T("FS") ); + +} + + +void TestName( const TCHAR* pchName, const TCHAR* pchGenre ) +{ + // + // set up name translator + // + iFCONameTranslator* mpCurNT = NULL; + cGenre::Genre gNTFS = cGenreSwitcher::GetInstance()->StringToGenre( pchGenre ); + ASSERT( gNTFS != cGenre::GENRE_INVALID ); + mpCurNT = cGenreSwitcher::GetInstance()->GetFactoryForGenre( gNTFS )->GetNameTranslator(); + + // + // encode name + // + cFCOName fcoName( pchName ); + TSTRING strName = mpCurNT->ToStringDisplay( fcoName, true ); + TCOUT << _T("from: <") << fcoName.AsString() << _T("> to:") << strName; + + // + // unencode name + // + cFCOName fcoNameNew; + ASSERT( mpCurNT->DisplayStringToFCOName( strName, fcoNameNew ) ); + TCOUT << _T("> back to: <") << fcoNameNew.AsString() << _T(">") << std::endl; + + // + // check result + // + ASSERT( fcoNameNew == fcoName ); +} + + +void TestUnprintable( const TCHAR* pchName, const TCHAR* pchGenre ) +{ + // + // set up name translator + // + iFCONameTranslator* mpCurNT = NULL; + cGenre::Genre gNTFS = cGenreSwitcher::GetInstance()->StringToGenre( pchGenre ); + ASSERT( gNTFS != cGenre::GENRE_INVALID ); + mpCurNT = cGenreSwitcher::GetInstance()->GetFactoryForGenre( gNTFS )->GetNameTranslator(); + + // + // encode name + // + cFCOName fcoName( pchName ); + TSTRING strName = mpCurNT->ToStringDisplay( fcoName, true ); + TCOUT << _T("To:") << strName; + + // + // unencode name + // + cFCOName fcoNameNew; + ASSERT( mpCurNT->DisplayStringToFCOName( strName, fcoNameNew ) ); + + // + // check result + // + ASSERT( fcoNameNew == fcoName ); +} + diff --git a/src/fco/fcoprop.h b/src/fco/fcoprop.h new file mode 100644 index 0000000..c9ec809 --- /dev/null +++ b/src/fco/fcoprop.h @@ -0,0 +1,81 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoprop.h +// +// iFCOProp -- abstract interface for all fco properties +#ifndef __FCOPROP_H +#define __FCOPROP_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __TYPED_H +#include "core/typed.h" +#endif +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif + +class iFCOProp : public iTypedSerializable +{ +public: + enum Op + { + OP_EQ = 1, // == + OP_NE = 2, // != + OP_GT = 4, // > + OP_LT = 8, // < + OP_GE = 16, // >= + OP_LE = 32 // <= + }; + enum CmpResult + { + CMP_TRUE = 1, + CMP_FALSE = 2, + CMP_WRONG_PROP_TYPE = 3, + CMP_UNSUPPORTED = 4 + }; + + virtual TSTRING AsString() const = 0; + // returns a string representation of the property + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const = 0; + virtual void Copy(const iFCOProp* rhs) = 0; + // change my value so that it is the same as the passed in property. + // this will assert() that the two properties are of the same type. + +protected: + virtual ~iFCOProp() {} +}; + +#endif //__FCOPROP_H + diff --git a/src/fco/fcopropcalc.h b/src/fco/fcopropcalc.h new file mode 100644 index 0000000..cf31513 --- /dev/null +++ b/src/fco/fcopropcalc.h @@ -0,0 +1,99 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropcalc.h +// +// iFCOPropCalc -- abstract interface for object that calculates fco properties +#ifndef __FCOPROPCALC_H +#define __FCOPROPCALC_H + +class cFCOPropVector; +class iFCOVisitor; +class iFCOSet; +class cErrorBucket; + + // cErrorBucket error numbers... +/* // the prop calculator owns all error numbers from 200-299 + enum ErrorNum + { + ERR_STAT_FAIL = 200, + ERR_GET_ACL_FAIL = 201, + ERR_NUM_ERRORS + }; +*/ + + +class iFCOPropCalc +{ +public: + virtual void SetPropVector(const cFCOPropVector& pv) = 0; + virtual const cFCOPropVector& GetPropVector() const = 0; + // gets and sets the property vector that indicates what properties the + // calculator will evaluate for each fco that it visits + + virtual iFCOVisitor* GetVisitor() = 0; + virtual const iFCOVisitor* GetVisitor() const = 0; + // returns 'this' if the class that implements this interface also implements + // iFCOVisitor, which will almost always be the case. Otherwise, these methods + // should return NULL + + virtual void SetErrorBucket(cErrorBucket* pBucket) = 0; + virtual const cErrorBucket* GetErrorBucket() const = 0; + + // this enum lists all the ways that the prop calc can behave when calculating a property + // that already has a valid value in an fco. The default behavior is PROP_LEAVE + enum CollisionAction + { + PROP_OVERWRITE, // overwite the existing value with a newly calculated one + PROP_LEAVE, // leave the existing property value (default) + PROP_NUMITEMS + }; + virtual CollisionAction GetCollisionAction() const = 0; + virtual void SetCollisionAction(CollisionAction a) = 0; + // these methods get and set the collision action for the property calculator + + + enum CalcFlags + { + DO_NOT_MODIFY_PROPERTIES = 0x00000001 // reset any properties that may have been altered due to measurement + }; + virtual int GetCalcFlags() const = 0; + virtual void SetCalcFlags(int i) = 0; + // any calculation flags needed for calculation. + + virtual ~iFCOPropCalc() {} + +}; + + +#endif //__FCOPROPCALC_H + diff --git a/src/fco/fcopropdisplayer.h b/src/fco/fcopropdisplayer.h new file mode 100644 index 0000000..3d3d7fe --- /dev/null +++ b/src/fco/fcopropdisplayer.h @@ -0,0 +1,176 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropdisplayer.h +// + +#ifndef __FCOPROPDISPLAYER_H +#define __FCOPROPDISPLAYER_H + +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif + +class iFCO; +class iFCOProp; +class cFCOPropVector; +class cFCOReport; +class cFCOName; + + +////////////////////// +// General: +////////////////////// +// +// In most cases, iFCOProp::AsString() is simply a 'dump' of the prop's +// internals. In order to display this property in a meaningful way to the +// user, it was decided that an auxillary class was needed to perform any +// formatting needed for displaying a property. +// +// The premise here is that it is a good idea to separate the data in the +// database from its text representation. The text representation of an FCO +// property may require information in addition to the property itself. For +// instance, while file size ( stored as an integer ) can simply be output to +// the screen using the stream operators, something like access time ( also +// stored as an int ) must be sent through ctime() or a similar +// number-to-string function, in order to be meaningful to the user. +// +// This class's job is to encapsulate the knowledge of how to turn the database +// representation of an FCO property into a text representation. The +// information needed may static, and known at compile time ( which can be as +// simple as knowing which system call to call for a certain property, such as +// ctime() for a time value ), or dynamically acquired information ( such as +// uid, which requires uid-to-username mapping information from the system ). +// +////////////////////////////// +// Major Functionality: +////////////////////////////// +// +// The main interface of this class is the PropAsString function, which +// returns a formatted string representing the property. +// +// Dynamic information is collected throught the InitForFCO or InitForProp, +// InitForProp simply being a subfunction of InitForFCO. +// +// This class also contains functionality to display an FCO and a few +// pre-defined properites. This function, GetDetails(), was designed to mimic +// a Unix 'ls -l listing' of the properties of the FCO. GetDetailsHeader() +// prints out the header for the listing. +// +////////////////////////////// +// Minor Functionality: +////////////////////////////// +// +// See implementation comments. +// +////////////////////////////// +// Relationships +////////////////////////////// +// +////////////////////////////// +// Typical Usage: +////////////////////////////// +// +// (1) At some time after the construction of an FCO, some component of +// tripwire will call InitForFCO() with the propdisplayer (PD) +// appropriate for the genre of the FCO. This retrieves and stores +// any information needed for displaying the FCO. +// (2) Later, when a property of the FCO needs to be displayed, +// the client will call PropAsString(). For any property that the +// PD does not know how to convert, the PD will simply return the +// result of the prop's AsString() function. So it is safe to call +// PropAsString() for all properties, even those it does not know +// how to display. +// (3) Merge() is used to consolidate PD information into one PD. So +// when performing a database update, the DB's PD will have to be +// merged with the report's PD. +// + +class iFCOPropDisplayer : public iTypedSerializable +{ +public: + virtual ~iFCOPropDisplayer() {}; + + virtual iFCOPropDisplayer* Clone() const = 0; + + virtual void Merge( const iFCOPropDisplayer* const ppd ) = 0; + // adds all prop display info from rhs to this. it is an error to merge two prop diplayers of different derived types + + virtual const cFCOPropVector& GetPropsConverted() const = 0; + // returns vector where if a given prop in the vector is valid, then this class + // can do a PropAsString that's different from the prop's own AsString() + + virtual TSTRING PropAsString( const iFCO* const pFCO, int const propIdx, int iOffset = 0, int iWidth = 0) const = 0; + virtual TSTRING PropAsString( const iFCO* const pFCO, int const propIdx, int iOffset = 0, int iWidth = 0) = 0; + // returns a more readable value than iFCOProp::AsString() (which simply returns a text version + // of the prop's value), (e.g. instead of calling fsprop(ATIME)::AsString() and getting 4578295721, + // you can call PropAsString to get "Sun Sep 26 1998" or the like.) If the displayer doesn't + // know how to display the property, simply returns iFCOProp::AsString() + // The non-const version will attempt to initialize the property if Lazy is set to true. + + // iOffset and iWidth should be used for multi-line properties; they only have meaning for lines + // after the first, so most single-line properties should ignore them. + // iOffset is the offset from ^ which each new line should start. + // iWidth is the space that the new line has ( uses setw( iWidth ) ). + + // the TSTRING returned should be convertable to a narrow string (that is, if there's any way that + // the prop could have funky wide chars, the string is put through cDisplayEncoder ) + + virtual bool IsMultiLineProp( int propID ) const = 0; + // returns true if PropAsString can return a string with \n's. + + virtual TSTRING& GetDetails( const iFCO* const pfco, TSTRING& strBuf ) const = 0; + // Returns a string with some of the FCO's genre specific properties. So, the + // output will look somewhat like the UNIX "ls -l" command except that the FCO name + // is not output + + virtual TSTRING& GetDetailsHeader( TSTRING& strBuf, int iMargin ) const = 0; + // describes output of GetDetails and is formatted just like it. To be used as a header. + // since the header is a two-lined output, it needs a margin for the second line + + virtual void InitForProp( const iFCO* const pFCO, const int propIdx ) = 0; + // InitForProp() is called to initialize the class's data structures to convert the passed + // property only. This can be used if there is only a small subset of the total system + // information that will actually be used, saving on memory and disk usage. + + virtual void InitForFCO( const iFCO* const ifco ) = 0; + // calls InitForProp on all valid props in ifco + + virtual void SetLazy( const bool bLazy = true ) = 0; + virtual bool GetLazy() const = 0; + // Get/SetLazy() is used for the lazy evaluation of the class's conversion data; if SetLazy(true) is called, + // then all PropAsString() calls will have an implicit InitForProp()call, if it is needed, before the conversion. +}; + + +#endif //__FCOPROPDISPLAYER_H + diff --git a/src/fco/fcopropimpl.cpp b/src/fco/fcopropimpl.cpp new file mode 100644 index 0000000..e222ad1 --- /dev/null +++ b/src/fco/fcopropimpl.cpp @@ -0,0 +1,287 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropimpl.cpp +// + +#include "stdfco.h" +#include "fcopropimpl.h" +#include "core/debug.h" +#include "fcoprop.h" +#include "core/serializer.h" +#include "fcoundefprop.h" +#include "core/errorutil.h" + +/////////////////////////////////////////////////////////////////////////////// +// DefaultCompare -- template function that implements compare in a way suitable +// for most fundamental types +/////////////////////////////////////////////////////////////////////////////// +template +/*static*/ +iFCOProp::CmpResult DefaultCompare(const TYPE* lhs, const iFCOProp* rhs, iFCOProp::Op op) +{ + // compares with undefined props are not equal + if (rhs->GetType() == cFCOUndefinedProp::GetInstance()->GetType()) + { + return (op == iFCOProp::OP_EQ) ? iFCOProp::CMP_FALSE : + (op == iFCOProp::OP_NE) ? iFCOProp::CMP_TRUE : + iFCOProp::CMP_WRONG_PROP_TYPE; + } + + // first, make sure we are the right type... + if(rhs->GetType() != lhs->GetType()) + { + return iFCOProp::CMP_WRONG_PROP_TYPE; + } + + // do the down cast + const TYPE* newRhs = static_cast(rhs); + ASSERT(newRhs != 0); + + // finally, do the comparison... + bool bResult; + switch(op) + { + case iFCOProp::OP_EQ: + bResult = (lhs->GetValue() == newRhs->GetValue()); + break; + case iFCOProp::OP_NE: + bResult = (lhs->GetValue() != newRhs->GetValue()); + break; + case iFCOProp::OP_GT: + bResult = (lhs->GetValue() > newRhs->GetValue()); + break; + case iFCOProp::OP_LT: + bResult = (lhs->GetValue() < newRhs->GetValue()); + break; + case iFCOProp::OP_GE: + bResult = (lhs->GetValue() >= newRhs->GetValue()); + break; + case iFCOProp::OP_LE: + bResult = (lhs->GetValue() <= newRhs->GetValue()); + break; + default: + // we have exhausted all the possibilities + ASSERT(false); + throw INTERNAL_ERROR("fcopropimpl.cpp"); + } + + return bResult? iFCOProp::CMP_TRUE : iFCOProp::CMP_FALSE; +} + +template +/*static*/ +void DefaultCopy(TYPE* lhs, const iFCOProp* rhs) +{ + // first, make sure we are the right type... + if(rhs->GetType() != lhs->GetType()) + { + ASSERT(false); + return; + } + + // do the down cast + const TYPE* newRhs = static_cast(rhs); + ASSERT(newRhs != 0); + lhs->SetValue(newRhs->GetValue()); +} + +//##################################### +// cFCOPropInt32 +//##################################### + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOPropInt32, _T("cFCOPropInt32"), 0, 1); + +TSTRING cFCOPropInt32::AsString() const +{ + //TODO:mdb -- implement this through twlocale! + // + TOSTRINGSTREAM ostr; + ostr.imbue( std::locale::classic() ); + ostr << mValue ; + return TSTRING(ostr.str()); +} + +iFCOProp::CmpResult cFCOPropInt32::Compare(const iFCOProp* rhs, iFCOProp::Op op) const +{ + return DefaultCompare(this, rhs, op); +} + +void cFCOPropInt32::Read(iSerializer* pSerializer, int32 version) +{ + if (version > 0) + ThrowAndAssert(eSerializerVersionMismatch(_T("Int32 Property Read"))); + + pSerializer->ReadInt32(mValue); +} + +void cFCOPropInt32::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(mValue); +} + +void cFCOPropInt32::Copy(const iFCOProp* rhs) +{ + DefaultCopy(this, rhs); +} + + + +//##################################### +// cFCOPropInt64 +//##################################### + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOPropInt64, _T("cFCOPropInt64"), 0, 1); + +TSTRING cFCOPropInt64::AsString() const +{ + //TODO:mdb -- implement this through twlocale! + // + TOSTRINGSTREAM ostr; + ostr.imbue( std::locale::classic() ); + ostr << (int32)mValue; + return TSTRING(ostr.str()); +} + +iFCOProp::CmpResult cFCOPropInt64::Compare(const iFCOProp* rhs, iFCOProp::Op op) const +{ + return DefaultCompare(this, rhs, op); +} + +void cFCOPropInt64::Read(iSerializer* pSerializer, int32 version) +{ + if (version > 0) + ThrowAndAssert(eSerializerVersionMismatch(_T("Int64 Property Read"))); + + pSerializer->ReadInt64(mValue); +} + +void cFCOPropInt64::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt64(mValue); +} + +void cFCOPropInt64::Copy(const iFCOProp* rhs) +{ + DefaultCopy(this, rhs); +} + + +//##################################### +// cFCOPropUint64 +//##################################### + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOPropUint64, _T("cFCOPropUint64"), 0, 1); + +TSTRING cFCOPropUint64::AsString() const +{ + //TODO:mdb -- implement this through twlocale! + // + TOSTRINGSTREAM ostr; + ostr.imbue( std::locale::classic() ); + ostr << (int32)mValue ; + return TSTRING(ostr.str()); +} + +iFCOProp::CmpResult cFCOPropUint64::Compare(const iFCOProp* rhs, iFCOProp::Op op) const +{ + return DefaultCompare(this, rhs, op); +} + +void cFCOPropUint64::Read(iSerializer* pSerializer, int32 version) +{ + if (version > 0) + ThrowAndAssert(eSerializerVersionMismatch(_T("uint64 Property Read"))); + + pSerializer->ReadInt64((int64&)mValue); +} + +void cFCOPropUint64::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt64(mValue); +} + +void cFCOPropUint64::Copy(const iFCOProp* rhs) +{ + DefaultCopy(this, rhs); +} + + +//##################################### +// cFCOPropTSTRING +//##################################### + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOPropTSTRING, _T("cFCOPropTSTRING"), 0, 1); + +TSTRING cFCOPropTSTRING::AsString() const +{ + return mValue; +} + +iFCOProp::CmpResult cFCOPropTSTRING::Compare(const iFCOProp* rhs, iFCOProp::Op op) const +{ + return DefaultCompare(this, rhs, op); +} + +void cFCOPropTSTRING::Read(iSerializer* pSerializer, int32 version) +{ + if (version > 0) + ThrowAndAssert(eSerializerVersionMismatch(_T("String Property Read"))); + + pSerializer->ReadString( mValue ); +} + +void cFCOPropTSTRING::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteString( mValue ); +} + +void cFCOPropTSTRING::Copy(const iFCOProp* rhs) +{ + DefaultCopy(this, rhs); +} + +//############################################################################# +// cFCOPropGrowingFile +//############################################################################# +iFCOProp::CmpResult cFCOPropGrowingFile::Compare(const iFCOProp* rhs, Op op) const +{ + // here is how the hack works: we want OP_EQ to return true if the file has grown (if rhs's + // size is bigger than or equal to mine) Therefore, equality is defined as my size being + // smaller than or equal to the rhs's size + if(op == OP_EQ) + return cFCOPropInt64::Compare(rhs, OP_LE); + else + return cFCOPropInt64::Compare(rhs, op); +} + + diff --git a/src/fco/fcopropimpl.h b/src/fco/fcopropimpl.h new file mode 100644 index 0000000..df436a3 --- /dev/null +++ b/src/fco/fcopropimpl.h @@ -0,0 +1,148 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropimpl.h -- implementation of some basic properties +// +#ifndef __FCOPROPIMPL_H +#define __FCOPROPIMPL_H + +#ifndef __FCOPROP_H +#include "fcoprop.h" +#endif +#ifndef __TYPES_H +#include "types.h" +#endif + + +///////////////////////////////////////////////////////////////// +// Another in my collection of macros, this just saves +// some redundant typing on my part. +#define PROP_DATA(TYPE)\ + private:\ + TYPE mValue;\ + public:\ + typedef TYPE ValueType;\ + TYPE GetValue() const { return mValue; }\ + void SetValue(const TYPE& v) { mValue = v; } +//////////////////////////////////////////////////////////////// + +class cFCOPropInt32 : public iFCOProp +{ +public: + PROP_DATA(int32) // see macro above + DECLARE_TYPEDSERIALIZABLE() // type information + + cFCOPropInt32() : mValue(0) {} + virtual ~cFCOPropInt32() {} + + // from iFCOProp + virtual TSTRING AsString() const; + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; + virtual void Copy(const iFCOProp* rhs); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +}; + +class cFCOPropInt64 : public iFCOProp +{ +public: + PROP_DATA(int64) // see macro above + DECLARE_TYPEDSERIALIZABLE() // type information + + cFCOPropInt64() : mValue(0) {} + virtual ~cFCOPropInt64() {} + + // from iFCOProp + virtual TSTRING AsString() const; + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; + virtual void Copy(const iFCOProp* rhs); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +}; + +class cFCOPropUint64 : public iFCOProp +{ +public: + PROP_DATA(uint64) // see macro above + DECLARE_TYPEDSERIALIZABLE() // type information + + cFCOPropUint64() : mValue(0) {} + virtual ~cFCOPropUint64() {} + + // from iFCOProp + virtual TSTRING AsString() const; + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; + virtual void Copy(const iFCOProp* rhs); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +}; + + +class cFCOPropTSTRING : public iFCOProp +{ +public: + PROP_DATA(TSTRING) // see macro above + DECLARE_TYPEDSERIALIZABLE() // type information + + cFCOPropTSTRING() : mValue(_T("")) {} + virtual ~cFCOPropTSTRING() {} + + // from iFCOProp + virtual TSTRING AsString() const; + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; + virtual void Copy(const iFCOProp* rhs); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOPropGrowingFile -- a property that represents a growing file. It does +// this by overriding Compare() and implementing it like less-than +// it is important, then, to note that this requires the fcos to be passed +// to the compare object in this order: old, new +/////////////////////////////////////////////////////////////////////////////// +class cFCOPropGrowingFile : public cFCOPropInt64 +{ +public: + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; +}; + +#endif //__FCOPROPIMPL_H + diff --git a/src/fco/fcopropimpl_t.cpp b/src/fco/fcopropimpl_t.cpp new file mode 100644 index 0000000..fae9953 --- /dev/null +++ b/src/fco/fcopropimpl_t.cpp @@ -0,0 +1,74 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcopropimpl_t.cpp +#include "stdfco.h" +#include "fcopropimpl.h" +#include "core/debug.h" + +void TestFCOPropImpl() +{ + cDebug d("TestFCOPropImpl"); + d.TraceDebug("Entering...\n"); + + // print the enum key: + d.TraceDebug("Output key:%d True\n%d False\n%d Wrong Type\n%d Unsupported\n", + iFCOProp::CMP_TRUE,iFCOProp::CMP_FALSE,iFCOProp::CMP_WRONG_PROP_TYPE,iFCOProp::CMP_UNSUPPORTED); + + + // test string rep + cFCOPropInt64 pi64; + cFCOPropUint64 pui64, pui64b; + pi64.SetValue(-456); + pui64.SetValue(456); + pui64b.SetValue(333); + d.TraceDebug(_T("property int64 = (should be -456) %s\n"), pi64.AsString().c_str()); + // test a few operators + d.TraceDebug("-456 < 456 (uint cmp to int should fail)= %d\n", pi64.Compare(&pui64, iFCOProp::OP_LT)); + cFCOPropInt64 p2i64; + p2i64.SetValue(4); + d.TraceDebug("-456 < 4 = %d\n", pi64.Compare(&p2i64, iFCOProp::OP_LT)); + d.TraceDebug("4 == 456 = %d\n", p2i64.Compare(&pi64, iFCOProp::OP_EQ)); + d.TraceDebug("333ui64 == 456ui64 = %d\n", pui64.Compare(&pui64b, iFCOProp::OP_EQ)); + cFCOPropTSTRING pt1; + cFCOPropTSTRING pt2; + pt1.SetValue(TSTRING(_T("bar"))); + pt2.SetValue(TSTRING(_T("foo"))); + d.TraceDebug(_T("property TSTRING = (should be \"bar\") %s\n"), pt1.AsString().c_str()); + d.TraceDebug(_T("property TSTRING = (should be \"foo\") %s\n"), pt2.AsString().c_str()); + d.TraceDebug("bar == foo = %d\n", pt1.Compare(&pt2, iFCOProp::OP_EQ)); + d.TraceDebug("bar == bar = %d\n", pt1.Compare(&pt1, iFCOProp::OP_EQ)); + d.TraceDebug("bar == 456 = %d\n", pt1.Compare(&pi64, iFCOProp::OP_EQ)); + + d.TraceDebug("Leaving...\n"); + return; +} + diff --git a/src/fco/fcopropset.h b/src/fco/fcopropset.h new file mode 100644 index 0000000..f10c144 --- /dev/null +++ b/src/fco/fcopropset.h @@ -0,0 +1,93 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropertyset.h +// +// iFCOPropSet -- the interface to an fco's properties +#ifndef __FCOPROPSET_H +#define __FCOPROPSET_H + +#ifndef __FCOPROPVECTOR_H +#include "fcopropvector.h" +#endif +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +class iFCOProp; + +class iFCOPropSet : public iTypedSerializable +{ +public: + enum { PROP_NOT_FOUND = -1 }; + + virtual const cFCOPropVector& GetValidVector() const = 0; + // returns a vector that indicates which properties have valid values associated with them. + + virtual int GetNumProps() const = 0; + // returns the number of properties this set has + + virtual int GetPropIndex(const TCHAR* name) const = 0; + // maps a property name to an index number. If the property doesn't exist in the set, -1 is returned. + // the return value is guarenteed to be in the range -1 <= x < GetNumProps() + + virtual TSTRING GetPropName(int index) const = 0; + // returns the name associated with the property at the given index. Return result is + // undefined if index is not in the range 0 <= index < GetNumProps() + + virtual const iFCOProp* GetPropAt(int index) const = 0; + virtual iFCOProp* GetPropAt(int index) = 0; + // returns a pointer to the property specified by index. Again, + // the return result is undefined if 0 <= index < GetNumProps() + + virtual void InvalidateProp (int index) = 0; + virtual void InvalidateProps(const cFCOPropVector& propsToInvalidate) = 0; + virtual void InvalidateAll () = 0; + // invalidates one, some, or all of the properties in this set + + virtual void CopyProps(const iFCOPropSet* pSrc, const cFCOPropVector& propsToCopy) = 0; + // copies the all the properties named in propsToCopy from pSrc to this prop set. + // this method will assert that pSrc is of the same type as this. All the properties + // in propsToCopy should be valid in pSrc. + + virtual void TraceContents(int dl = -1) const = 0; + // sends the contents of this property set to wherever cDebug is pointing. + +protected: + virtual ~iFCOPropSet() {} +}; + +#endif //__FCOPROPSET_H + diff --git a/src/fco/fcopropsetimpl.cpp b/src/fco/fcopropsetimpl.cpp new file mode 100644 index 0000000..b8045f0 --- /dev/null +++ b/src/fco/fcopropsetimpl.cpp @@ -0,0 +1,212 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// propsetimpl.cpp + +#include "stdfs.h" +#include "propsetimpl.h" + +#include "core/debug.h" +#include "core/serializer.h" +#include "core/errorutil.h" +#include "fco/fcoundefprop.h" + + /////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cPropSetImpl::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cPropSetImpl::TraceContents"); + + TOSTRINGSTREAM ostr; + ostr << _T("File Sysytem Prop Set: "); + for(int i=0; iGetType() == CLASS_TYPE(cPropSetImpl)); + + // first, modify my valid vector... + mValidProps |= propsToCopy; + + for(int i=0; i < GetNumFSProps(); i++) + { + if(propsToCopy.ContainsItem(i)) + { + ASSERT( pSrc->GetValidVector().ContainsItem( i ) ); + const iFCOProp* pProp = pSrc->GetPropAt(i); + + if (pProp->GetType() != cFCOUndefinedProp::GetInstance()->GetType()) + { + GetPropAt(i)->Copy( pProp ); + mUndefinedProps.RemoveItem(i); + } + else + mUndefinedProps.AddItem(i); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Invalidate +/////////////////////////////////////////////////////////////////////////////// +void cPropSetImpl::InvalidateProp(int index) +{ + ASSERT((index >= 0) && (index < GetNumProps())); + mValidProps.RemoveItem(index); +} + +void cPropSetImpl::InvalidateAll() +{ + mValidProps.Clear(); +} + +void cPropSetImpl::InvalidateProps(const cFCOPropVector& propsToInvalidate) +{ + cFCOPropVector inBoth = mValidProps; + inBoth &= propsToInvalidate; + mValidProps ^= inBoth; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetNumFSProps +/////////////////////////////////////////////////////////////////////////////// +int cPropSetImpl::GetNumFSProps() +{ + return PROP_NUMITEMS; +} + +/////////////////////////////////////////////////////////////////////////////// +// ctors. dtor, operator= +/////////////////////////////////////////////////////////////////////////////// +cPropSetImpl::cPropSetImpl() : + mValidProps(cPropSetImpl::PROP_NUMITEMS), + mUndefinedProps(cPropSetImpl::PROP_NUMITEMS) +{ + // TODO: do I want to zero out all the property values here? +} + +cPropSetImpl::~cPropSetImpl() +{ + +} + +cPropSetImpl::cPropSetImpl(const cPropSetImpl& rhs) : + mValidProps(cPropSetImpl::PROP_NUMITEMS) +{ + *this = rhs; +} + +const cPropSetImpl& cPropSetImpl::operator=(const cPropSetImpl& rhs) +{ + mValidProps = rhs.GetValidVector(); + mUndefinedProps = rhs.mUndefinedProps; + + for(int i=0; i < PROP_NUMITEMS; i++) + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Copy( ((cPropSetImpl&)rhs).GetPropAt(i) ); // call non-const GetPropAt for rhs + // don't want it to assert ContainsItem + return *this; +} + +const cFCOPropVector& cPropSetImpl::GetValidVector() const +{ + return mValidProps; +} + +int cPropSetImpl::GetNumProps() const +{ + return PROP_NUMITEMS; +} + +/* +int cPropSetImpl::GetPropIndex(const TCHAR* name) const +{ + for(int i=0; i= 0) && (index < GetNumProps())); + return TSS_GetString( cFS, cPropSetImpl_PropNames[index]); +} + + */ +void cPropSetImpl::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Property Set Read"))); + + mValidProps.Read(pSerializer); + mUndefinedProps.Read(pSerializer); + + for (int i=0; i < PROP_NUMITEMS; i++) + { + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Read(pSerializer); + } +} + +void cPropSetImpl::Write(iSerializer* pSerializer) const +{ + mValidProps.Write(pSerializer); + mUndefinedProps.Write(pSerializer); + + for (int i=0; i < PROP_NUMITEMS; i++) + { + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Write(pSerializer); + } +} + + diff --git a/src/fco/fcopropsetimpl.h b/src/fco/fcopropsetimpl.h new file mode 100644 index 0000000..2f185ab --- /dev/null +++ b/src/fco/fcopropsetimpl.h @@ -0,0 +1,78 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropsetimpl.h -- file system objects' property set objects +// +// cPropSetImpl -- base class for all prop sets +// contains common implementation + +#ifndef __FSPROPSETIMPL_H +#define __FSPROPSETIMPL_H + +#ifndef __FCOPROPSET_H +#include "fco/fcopropset.h" +#endif +#ifndef __PROPSET_H +#include "fco/propset.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// cPropSetImpl +/////////////////////////////////////////////////////////////////////////////// +class cPropSetImpl : public iFCOPropSet +{ +public: + cFSPropSet(); + cFSPropSet(const cFSPropSet& rhs); + virtual ~cFSPropSet(); + + const cFSPropSet& operator=(const cFSPropSet& rhs); + + virtual const cFCOPropVector& GetValidVector() const ; + virtual int GetNumProps () const ; + virtual int GetPropIndex(const TCHAR* name) const; + virtual TSTRING GetPropName (int index) const; + virtual const iFCOProp* GetPropAt(int index) const; + virtual iFCOProp* GetPropAt(int index) ; + virtual void InvalidateProp(int index); + virtual void InvalidateProps(const cFCOPropVector& propsToInvalidate) ; + virtual void InvalidateAll(); + virtual void CopyProps(const iFCOPropSet* pSrc, const cFCOPropVector& propsToCopy); + +private: + cFCOPropVector mValidProps; // all the properties that have been evaluated + cFCOPropVector mUndefinedProps; // properties that have been measured but have undefined values +}; + + +#endif // #ifndef __FSPROPSETIMPL_H + diff --git a/src/fco/fcopropvector.cpp b/src/fco/fcopropvector.cpp new file mode 100644 index 0000000..4241c1c --- /dev/null +++ b/src/fco/fcopropvector.cpp @@ -0,0 +1,454 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcopropvector.cpp +// + +#include "stdfco.h" +#include "fcopropvector.h" +#include "core/serializer.h" +#include "core/debug.h" +#include "core/errorutil.h" + +int cFCOPropVector::msBitlength(sizeof (uint32) * 8); + //msBitlength is common to all objects of class. + +/////////////////////////////////////////////////////////////////////////////// +// Constructor -- Sets mSize. Default = 32. +/////////////////////////////////////////////////////////////////////////////// +cFCOPropVector::cFCOPropVector(int size) +{ + mSize = 32; + mMask = 0; + mpBuf = NULL; + SetSize(size); +} + +/////////////////////////////////////////////////////////////////////////////// +// Destructor -- +/////////////////////////////////////////////////////////////////////////////// +cFCOPropVector::~cFCOPropVector() +{ + if (mpBuf!=NULL) + delete mpBuf; +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy Constructor +/////////////////////////////////////////////////////////////////////////////// +cFCOPropVector::cFCOPropVector(const cFCOPropVector &rhs) +{ + mSize = rhs.mSize; + mMask = rhs.mMask; + if (rhs.mpBuf != NULL) { + mpBuf = new std::vector; + *mpBuf = *(rhs.mpBuf); + } + else mpBuf = NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// Overloaded Operators: ==, !=, = , &, |, &=, |= +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::operator==(const cFCOPropVector& rhs) const +{ + if (this != &rhs) { + if ((mpBuf == NULL) && (rhs.mpBuf==NULL)) + return (mMask == rhs.mMask); + else if((mpBuf == NULL) && (rhs.mpBuf!=NULL)) + { + if (rhs.isExtended()) + return false; + else + return (mMask == ((*rhs.mpBuf)[0])); + } + else if ((mpBuf != NULL) && (rhs.mpBuf == NULL)) + { + if ((*this).isExtended()) + return false; + else + return (((*mpBuf)[0])==rhs.mMask); + } + else + return (*mpBuf == *(rhs.mpBuf)); + } + else + return true; +} + +bool cFCOPropVector::operator!=(const cFCOPropVector& rhs) const +{ + return (! (*this == rhs)); +} + + + +cFCOPropVector& cFCOPropVector::operator=(const cFCOPropVector& rhs) +{ + if (this != &rhs) + { + if ((rhs.mpBuf!=NULL) && (mpBuf!=NULL)) + *mpBuf= *(rhs.mpBuf); + else if ((rhs.mpBuf!=NULL) && (mpBuf==NULL)) + { + mpBuf = new std::vector; + *mpBuf = *(rhs.mpBuf); + } + else if((rhs.mpBuf==NULL) && (mpBuf!=NULL)) + { + delete mpBuf; + mpBuf = NULL; + } + mSize = rhs.mSize; + mMask = rhs.mMask; + }//end if + return *this; +} + +cFCOPropVector cFCOPropVector::operator&(const cFCOPropVector& rhs) const +{ + cFCOPropVector temp = *this; + temp &= rhs; + return temp; +} + +cFCOPropVector cFCOPropVector::operator|(const cFCOPropVector& rhs) const +{ + cFCOPropVector temp = *this; + temp |= rhs; + return temp; +} + +cFCOPropVector cFCOPropVector::operator^(const cFCOPropVector& rhs) const +{ + cFCOPropVector temp = *this; + temp ^= rhs; + return temp; +} + + +cFCOPropVector& cFCOPropVector::operator&=(const cFCOPropVector& rhs) +{ + // make sure I am big enough + if(GetSize() < rhs.GetSize()) + SetSize(rhs.GetSize()); + if(mpBuf == 0) + { + ASSERT(GetSize() <= 32); + mMask &= rhs.mMask; + } + else if (rhs.mpBuf == 0) + { + ASSERT(rhs.GetSize() <= 32); + (*mpBuf)[0] &= rhs.mMask; + } + else + { + for(unsigned int i=0; i < rhs.mpBuf->size(); ++i) + (*mpBuf)[i] &= (*rhs.mpBuf)[i]; + } + return *this; +} + +cFCOPropVector& cFCOPropVector::operator|=(const cFCOPropVector& rhs) +{ + // make sure I am big enough + if(GetSize() < rhs.GetSize()) + SetSize(rhs.GetSize()); + if(mpBuf == 0) + { + ASSERT(GetSize() <= 32); + mMask |= rhs.mMask; + } + else if (rhs.mpBuf == 0) + { + ASSERT(rhs.GetSize() <= 32); + (*mpBuf)[0] |= rhs.mMask; + } + else + { + for(unsigned int i=0; i < rhs.mpBuf->size(); ++i) + (*mpBuf)[i] |= (*rhs.mpBuf)[i]; + } + return *this; +} + +cFCOPropVector& cFCOPropVector::operator^=(const cFCOPropVector& rhs) +{ + // make sure I am big enough + if(GetSize() < rhs.GetSize()) + SetSize(rhs.GetSize()); + if(mpBuf == 0) + { + ASSERT(GetSize() <= 32); + mMask ^= rhs.mMask; + } + else if (rhs.mpBuf == 0) + { + ASSERT(rhs.GetSize() <= 32); + (*mpBuf)[0] ^= rhs.mMask; + } + else + { + for(unsigned int i=0; i < rhs.mpBuf->size(); ++i) + (*mpBuf)[i] ^= (*rhs.mpBuf)[i]; + } + return *this; +} + + + +//END OPERATORS + +/////////////////////////////////////////////////////////////////////////////// +// GetSize -- returns the number of items the vector can hold +/////////////////////////////////////////////////////////////////////////////// +int cFCOPropVector::GetSize(void) const +{ + return mSize; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetSize -- Sets the maximum NUMBER of items that can be stored +// in vector. **IMPORTANT** : If max is less than current size of mask+buff, +// the set is truncated and extra information is lost. +/////////////////////////////////////////////////////////////////////////////// +int cFCOPropVector::SetSize(int max) +{ + if ((max <= msBitlength) && (mpBuf == NULL)) + return mSize = msBitlength; + else if ((max <= msBitlength) && (mpBuf != NULL)) + { + return mSize = (*mpBuf).capacity()*msBitlength; + //new operation already performed, stick with mpBuf. + } + else if ((mpBuf == NULL) && (max > msBitlength)) + { + mpBuf = new std::vector; + (*mpBuf).resize (((max/msBitlength)+1), 0); + (*mpBuf)[0] = mMask; + return mSize = ((*mpBuf).capacity() * msBitlength); + } + else //mpBuf!=NULL && max>msBitlength + { + (*mpBuf).resize (((max/msBitlength)+1), 0); + return mSize = ((*mpBuf).capacity() * msBitlength); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// AddItem -- Adds an item to the bitset by 'anding' it on. Behavior is +// undefined if i >= GetSize. Returns true if set contains item after change. +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::AddItem(int i) +{ + ASSERT(i < GetSize()); + + if (mpBuf == NULL) + { + ASSERT(mSize <= 32); + mMask |= 1<<(i); + } + else + { + ((*mpBuf)[(i)/msBitlength]) |= 1<<((i) % msBitlength); + } + return ContainsItem(i); +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddItemAndGrow -- Like AddItem except that if i >= GetSize, resizes vector. +// Returns true if set contains item after change. +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::AddItemAndGrow(int i) +{ + if(i >= GetSize()) + SetSize( i ); + + return AddItem( i ); +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveItem -- Removes an item from the vector. Vector is unchanged if +// i >= GetMaxItem. Returns true if set does not contain item after change. +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::RemoveItem(int i) +{ + ASSERT(i < GetSize()); + + if (!ContainsItem(i)) + return true; + if (mpBuf == NULL) + mMask ^= 1<<(i); + else + { + ((*mpBuf)[(i)/msBitlength]) ^= 1<<((i) % msBitlength); + } + return !ContainsItem(i); +} + +/////////////////////////////////////////////////////////////////////////////// +// ContainsItem -- Returns boolean value if bit value is in the vector. +// Fails if mMask+mBuf is < i. +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::ContainsItem(int i) const +{ + if (i > mSize-1) + return false; + else if (mpBuf == NULL) + { + return ((mMask & (1<<(i))) != 0); + } + else + { + return ((((*mpBuf)[(i)/msBitlength]) & (1<<((i) % msBitlength))) != 0); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear -- removes all items from the vector +/////////////////////////////////////////////////////////////////////////////// +void cFCOPropVector::Clear(void) +{ + mMask = 0; + if(mpBuf) + { + std::fill(mpBuf->begin(), mpBuf->end(), 0); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// isExtended -- Returns true if Vector is USING mpBuf beyond [0]. It +// is assumed that {mpBuf [i] |i>0} is being used if i has non-zero value. +/////////////////////////////////////////////////////////////////////////////// +bool cFCOPropVector::isExtended(void) const +{ + if (mpBuf == NULL) + return false; + else + { + if ((*mpBuf).size() <= 1) + return false; + else + { + int sum = 0; + for (int i=(*mpBuf).size(); i >= 2; i--) + sum += ((*mpBuf)[i]); + return (sum == 0); + } + } +} + + +// TO DO: temp function, will delete after testing... DA +void cFCOPropVector::check (cDebug& d) const +{ + d.TraceDetail("mSize = %i \n", mSize); + d.TraceDetail("msBitlength = %i \n", msBitlength); + d.TraceDetail("mMask = %u \n", mMask); + if (mpBuf!=NULL) { + d.TraceDetail("*mpBuf has size %i \n", (*mpBuf).size() ); + for (unsigned int i = 0; i<(*mpBuf).size(); ++i) + d.TraceDetail("mpBuf element %i = %u \n", i, (*mpBuf)[i] ); + } +}//end check + + +void cFCOPropVector::Read(iSerializer* pSerializer, int32 version) +{ + if (version > 0) + ThrowAndAssert(eSerializerVersionMismatch(_T("Property Vector Read"))); + + int i; + int32 newSize; + pSerializer->ReadInt32(newSize); + ASSERT(newSize > 0); + + SetSize(newSize); + + if (mpBuf == NULL) + { + int32 mask; + pSerializer->ReadInt32(mask); + mMask = mask; + } + else + { + for (i=0; i <= mSize / msBitlength; ++i) + { + int32 mask; + pSerializer->ReadInt32(mask); + (*mpBuf)[i] = mask; + } + } + +} + +void cFCOPropVector::Write(iSerializer* pSerializer) const +{ + int i; + pSerializer->WriteInt32(mSize); + + if (mpBuf == NULL) + { + pSerializer->WriteInt32(mMask); + } + else + { + for (i=0; i <= mSize / msBitlength; ++i) + pSerializer->WriteInt32((*mpBuf)[i]); + } + +} + + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents -- prints the contents of the vector to debug out +/////////////////////////////////////////////////////////////////////////////// +void cFCOPropVector::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFCOPropVector::TraceContents"); + TOSTRINGSTREAM ostr; + for(int i=0; i GetSize() + bool AddItemAndGrow (int i); + // Adds the item i to the vector. if (i > GetSize()), grows the vector + bool RemoveItem (int i); + // Removes an item from the set if it is in the set. Returns true if the + // item is not in the set prior to call. + bool ContainsItem (int i) const; + // returns true if the item is in the set. Returns false if i>GetSize. + void Clear (void); + // removes all items from the vector... + void check (cDebug& d) const; + // Temp function for testing purposes. Outputs vector info. TO DO: + // Get rid of this when it's no longer useful! DA + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + // iSerializable interface + void TraceContents (int dl = -1) const; + // debugging utility; traces out the contents of the vector + +private: + bool isExtended (void) const; + // Helper function that discerns if an object is using mpBuf beyond [0] + + int mSize; + static int msBitlength; + uint32 mMask; + std::vector *mpBuf; +}; + +#endif //__FCOPROPVECTOR_H + diff --git a/src/fco/fcopropvector_t.cpp b/src/fco/fcopropvector_t.cpp new file mode 100644 index 0000000..1b39571 --- /dev/null +++ b/src/fco/fcopropvector_t.cpp @@ -0,0 +1,250 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcopropvector_t.cpp -- class cFCOPropVector's test harness +#include "stdfco.h" +#include "fcopropvector.h" + +#ifndef __TEST_H +#include "test/test.h" +#endif + +static bool init (cFCOPropVector &testV); +static bool addRemove (cFCOPropVector &test1, cFCOPropVector &test2, cDebug& d); +static bool objManip (cFCOPropVector &testV, cDebug& d); + +void TestFCOPropVector() +{ + //Local Variables for main test function + + bool testout; + cDebug d("TestFCOPropVector()"); + d.TraceDetail("Entering...\n"); + + cFCOPropVector test1, test2, test3; + + test1.SetSize(32); + test2.SetSize(64); + test3.SetSize(45); + + d.TraceDetail("Empty Vector with no buffer:\n"); + test1.check(d); + d.TraceDetail("\nEmpty Vector with buffer used: \n"); + test2.check(d); + d.TraceDetail("\nEmpty Vector with buffer, mSize less buffer capacity: \n"); + test3.check(d); + + //First, test set initialization is correct. + d.TraceDetail("\nTesting vector initialization...\n"); + TEST(testout = (init (test1)) & (init(test2)) & (init(test3))); + if (testout) + d.TraceDetail("success.\n"); + else { + test1.check(d); + test2.check(d); + test3.check(d); + } + + //Test ability to add and remove + TEST(testout = addRemove (test1, test2, d)); + d.TraceDetail("Add/Remove over all tests is %i \n", testout); + + // test clear. + d.TraceDetail("Testing Clear()\n"); + d.TraceDetail("Filling with numbers...\n"); + cFCOPropVector v(44); + v.AddItem(2); + v.AddItem(3); + v.AddItem(9); + v.AddItem(40); + v.check(d); + d.TraceDetail("Clearing Numbers...\n"); + v.Clear(); + v.check(d); + d.TraceDetail("Clear Test Done.\n"); + + //test operators + TEST(testout = objManip(test1, d)); + if (testout) + d.TraceDetail("Object manipulation tests are successful\n"); + else + d.TraceDetail("Object manipulation tests are not successful\n"); + + return; +}//end TestPropVector + +static bool init (cFCOPropVector &testV) +{ + int range = testV.GetSize()-1; + + for (int i=1; i<=range; ++i) + { + if (testV.ContainsItem(i)) + return false; + } //end for + return true; +} //end init + +static bool addRemove (cFCOPropVector &test1, cFCOPropVector &test2, cDebug& d) +{ + int var1 = 0 , var2 = 64, var3 = 2; + bool local=true, out=true; + + /* + bool loopvar = true; + int menu, var; + cFCOPropVector testV; + testV.SetSize(64); + while (loopvar) + { + + d.TraceAlways("\nChoose an operation to test:\n"); + d.TraceAlways("\t1)Add an item to vector.\n"); + d.TraceAlways("\t2)Remove an item from vector. \n"); + d.TraceAlways("\t3)Check vector for item. \n"); + d.TraceAlways("\t4)Display vector information \n"); + d.TraceAlways("\t5)Stop add/remove tests. \n"); + d.TraceAlways("Your choice [1-5]: "); + cin>>menu; + d.TraceAlways("\n"); + + switch (menu) + { + case 1: + d.TraceAlways("Item to add: "); + cin>> var; + d.TraceAlways("%i \n", testV.AddItem(var)); + break; + case 2: + d.TraceAlways("Item to remove: "); + cin>>var; + d.TraceAlways("%i \n", testV.RemoveItem(var)); + break; + case 3: + d.TraceAlways("Item to check: "); + cin>>var; + if (testV.ContainsItem(var)) + d.TraceAlways("\nItem present\n"); + else + d.TraceAlways("\nItem not present\n"); + break; + case 4: + testV.check(d); + break; + case 5: + loopvar = false; + break; + default: + d.TraceAlways("Not a valid menu option\n"); + break; + }//end switch + out &= local; //Keep track of results. + }//end while + */ + + test1.AddItem(var1); + TEST(local &= test1.ContainsItem(var1)); //hopefully this is true! + TEST(local &= !test1.ContainsItem(var3)); + test2.SetSize(var2); + TEST(local &= (test2.GetSize() == ((var2/32)+1)*32)); + TEST(local &= (test1 != test2)); + test1.RemoveItem(var1); + test2.SetSize(test1.GetSize()); + TEST(local &= (test1 == test2)); + test1.AddItem(var3); + test2 |= test1; + d.TraceDetail("\nmMask should be 4!\n"); + test2.check(d); + test2.RemoveItem(var3); + d.TraceDetail("\nmMask should be 0! \n"); + test2.check(d); + + out &= local; //and-ing of results. + return out; +}//end addRemove + +static bool objManip (cFCOPropVector &testV, cDebug& d) +{ + cFCOPropVector test1, test2 = testV; + bool out = true; + + /*testV.check(d); + test2.check(d);*/ + + TEST(out &= (testV == test2)); //test operator = , == + test2.AddItem(1); + TEST(out &= (testV != test2)); //test operator != + + /*testV.check(d); + test2.check(d);*/ + + testV &= test2; //test operator &= + testV.check(d); + testV |= test2; //test operator |= + testV.check(d); + + test1 = testV | test2; //test operator | + test1.check(d); + TEST(out&= (test1 == testV)); + + test2.RemoveItem(1); + testV = (test2 & test1);//test operator & + testV.check(d); + TEST(out&= !(test1 == testV)); + + // test operator ^ + cFCOPropVector v1, v2, v3; + v1.AddItem(1); + v1.AddItem(3); + v1.AddItem(4); + v2.AddItem(3); + // expected result + v3.AddItem(1); + v3.AddItem(4); + TEST((v1 ^ v2) == v3); + // try with larger sizes... + v2.SetSize(40); + v2.Clear(); + v2.AddItem(3); + TEST((v1 ^ v2) == v3); + v2.AddItem(38); + v1.SetSize(40); + v1.Clear(); + v1.AddItem(1); + v1.AddItem(38); + v3.SetSize(40); + v3.Clear(); + v3.AddItem(1); + v3.AddItem(3); + TEST((v1 ^ v2) == v3); + + return out; +}//end objManip diff --git a/src/fco/fcosetimpl.cpp b/src/fco/fcosetimpl.cpp new file mode 100644 index 0000000..50a48dd --- /dev/null +++ b/src/fco/fcosetimpl.cpp @@ -0,0 +1,325 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcosetimpl.cpp +// + +#include "stdfco.h" +#include "fconame.h" +#include "fcosetimpl.h" +#include "core/serializer.h" +#include "core/debug.h" +#include "core/errorutil.h" + + +//################################################################ +// cFCOSetImpl +//################################################################ + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOSetImpl, _T("cFCOSetImpl"), 0, 1) + +/////////////////////////////////////////////////////////////////////////////// +// CreateIterator -- creates a new iterator for the passed class +/////////////////////////////////////////////////////////////////////////////// +inline static cFCOIterImpl* CreateIterator(cFCOSetImpl* pSet) +{ + return new cFCOIterImpl(pSet); +} + +inline static const cFCOIterImpl* CreateIterator(const cFCOSetImpl* pSet) +{ + return new cFCOIterImpl(pSet); +} + +/////////////////////////////////////////////////////////////////////////////// +// ctor and dtor +/////////////////////////////////////////////////////////////////////////////// +cFCOSetImpl::cFCOSetImpl() +{ +} + +cFCOSetImpl::~cFCOSetImpl() +{ + Clear(); +} + +cFCOSetImpl::cFCOSetImpl(const cFCOSetImpl& rhs) +{ + *this = rhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +void cFCOSetImpl::operator=(const cFCOSetImpl& rhs) +{ + std::set::const_iterator i; + for(i = rhs.mFCOSet.begin(); i != rhs.mFCOSet.end(); ++i) + { + i->mpFCO->AddRef(); + mFCOSet.insert(cFCONode(i->mpFCO)); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Clear -- remove all elements from the set... +/////////////////////////////////////////////////////////////////////////////// +void cFCOSetImpl::Clear() +{ + // release our grip on all the fcos. + std::set::iterator i; + for(i = mFCOSet.begin(); i != mFCOSet.end(); ++i) + { + i->mpFCO->Release(); + } + + mFCOSet.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// IsEmpty -- Anything in the set? +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSetImpl::IsEmpty() const +{ + return mFCOSet.empty(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Lookup -- TODO: figure out how I can implement const and non-const versions +// without duplicating code. +/////////////////////////////////////////////////////////////////////////////// +const iFCOIter* cFCOSetImpl::Lookup(const cFCOName& name) const +{ + const cFCOIterImpl* pIter = CreateIterator(this); + if(! pIter->SeekToFCO(name)) + { + pIter->DestroyIter(); + pIter = NULL; + } + return pIter; +} + +iFCOIter* cFCOSetImpl::Lookup(const cFCOName& name) +{ + cFCOIterImpl* pIter = CreateIterator(this); + if(! pIter->SeekToFCO(name)) + { + pIter->DestroyIter(); + pIter = NULL; + } + return pIter; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetIter +/////////////////////////////////////////////////////////////////////////////// +const iFCOIter* cFCOSetImpl::GetIter() const +{ + return CreateIterator(this); +} + +iFCOIter* cFCOSetImpl::GetIter() +{ + return CreateIterator(this); +} + +void cFCOSetImpl::ReturnIter(const cFCOIterImpl* pIter) const +{ + delete pIter; +} + +/////////////////////////////////////////////////////////////////////////////// +// Insertion +/////////////////////////////////////////////////////////////////////////////// +void cFCOSetImpl::Insert(iFCO* pFCO) +{ + + //TODO -- how do I handle the insertion of the same fco into the set? + // should it be a no-op, added twice, asserted, or an exception? + std::pair::iterator, bool> p; + p = mFCOSet.insert(cFCONode(pFCO)); + // if the element already existed in the set, p.second is false. + ASSERT(p.second); + if(p.second) + pFCO->AddRef(); +} + +/////////////////////////////////////////////////////////////////////////////// +// AcceptSerializer +/////////////////////////////////////////////////////////////////////////////// +void cFCOSetImpl::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("FCO Set Read"))); + + Clear(); + + int i; + int32 size; + pSerializer->ReadInt32(size); + + // TODO -- don't assert; throw an exception or noop -- mdb + //ASSERT(size >= 0); + + for (i = 0; i < size; ++i) + { + iTypedSerializable* pObj = pSerializer->ReadObjectDynCreate(); + mFCOSet.insert(static_cast(pObj)); + } +} + +void cFCOSetImpl::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(mFCOSet.size()); + + std::set::const_iterator itr; + for( itr = mFCOSet.begin(); itr != mFCOSet.end(); itr++) + { + pSerializer->WriteObjectDynCreate(itr->mpFCO); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFCOSetImpl::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFCOSetImpl::TraceContents"); + std::set::const_iterator i; + int count = 0; + for(i = mFCOSet.begin(); i != mFCOSet.end(); ++i, ++count) + { + d.Trace(dl, "[FCO %d]\n", count); + i->mpFCO->TraceContents(dl); + } +} + + +//################################################################ +// cFCOIterImpl +//################################################################ + +/////////////////////////////////////////////////////////////////////////////// +// ctor and dtor +/////////////////////////////////////////////////////////////////////////////// +cFCOIterImpl::cFCOIterImpl(cFCOSetImpl* pSet) : + mpSet(pSet), + mIter() +{ + mIter = mpSet->mFCOSet.begin(); +} + +cFCOIterImpl::cFCOIterImpl(const cFCOSetImpl* pSet) : + mpSet((cFCOSetImpl *)pSet), + mIter() +{ + mIter = mpSet->mFCOSet.begin(); +} + +cFCOIterImpl::~cFCOIterImpl() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekToFCO +/////////////////////////////////////////////////////////////////////////////// +bool cFCOIterImpl::SeekToFCO(const cFCOName& name) const +{ + mIter = mpSet->mFCOSet.find(cFCOSetImpl::cFCONode(name)); + return (mIter != mpSet->mFCOSet.end()); +} + + +void cFCOIterImpl::SeekBegin() const +{ + ASSERT(mpSet != 0); + mIter = mpSet->mFCOSet.begin(); +} + + +bool cFCOIterImpl::Done() const +{ + ASSERT(mpSet != 0); + return (mIter == mpSet->mFCOSet.end()); +} + +bool cFCOIterImpl::IsEmpty() const +{ + ASSERT(mpSet != 0); + return (mpSet->mFCOSet.empty()); +} + +void cFCOIterImpl::Next() const +{ + ASSERT(mpSet != 0); + mIter++; +} + + +const iFCO* cFCOIterImpl::FCO() const +{ + return mIter->mpFCO; +} + +iFCO* cFCOIterImpl::FCO() +{ + return mIter->mpFCO; +} + +void cFCOIterImpl::Remove() +{ + ASSERT(mpSet != 0); + ASSERT(mIter != mpSet->mFCOSet.end()); + mIter->mpFCO->Release(); + mpSet->mFCOSet.erase(mIter++); +} + + +void cFCOIterImpl::Remove() const +{ + ASSERT(mpSet != 0); + ASSERT(mIter != mpSet->mFCOSet.end()); + mIter->mpFCO->Release(); + mpSet->mFCOSet.erase(mIter++); +} + + +void cFCOIterImpl::DestroyIter() const +{ + ASSERT(mpSet != 0); + mpSet->ReturnIter(this); +} + + diff --git a/src/fco/fcosetimpl.h b/src/fco/fcosetimpl.h new file mode 100644 index 0000000..75f6974 --- /dev/null +++ b/src/fco/fcosetimpl.h @@ -0,0 +1,129 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcosetimpl.h +// +// class cFCOSetImpl -- concrete implementation of an FCO set +// class cFCOIterImpl -- the iterator over the set +#ifndef __FCOSETIMPL_H +#define __FCOSETIMPL_H + +#ifndef __FCO_H +#include "fco.h" +#endif +#include "fconame.h" + +#ifndef __FCONAME_H +#include "fconame.h" +#endif +class cFCOIterImpl; + +class cFCOSetImpl : public iFCOSet +{ + friend class cFCOIterImpl; + DECLARE_TYPEDSERIALIZABLE() + +public: + cFCOSetImpl(); + cFCOSetImpl(const cFCOSetImpl& rhs); + virtual ~cFCOSetImpl(); + void operator=(const cFCOSetImpl& rhs); + + virtual const iFCOIter* Lookup(const cFCOName& name) const; + virtual iFCOIter* Lookup(const cFCOName& name); + virtual const iFCOIter* GetIter() const; + virtual iFCOIter* GetIter(); + virtual void Insert(iFCO* pFCO); + virtual void Clear(); + virtual bool IsEmpty() const; + virtual int Size() const { return mFCOSet.size(); }; + virtual void TraceContents(int dl = -1) const; + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +private: + void ReturnIter(const cFCOIterImpl* pIter) const; + // returns the iterator to its owner; the reciprocal action + // to Lookup() or GetIter(); called by the iterator when it is destroyed + + // class we store in the set below; it is a hack that allows us to + // look up iFCOs using cFCONames in a std::set + class cFCONode + { + public: + iFCO* mpFCO; + const cFCOName* mpFCOName; + + cFCONode() : mpFCO(0), mpFCOName(0) {} + cFCONode(iFCO* pFCO) : mpFCO(pFCO), mpFCOName(&pFCO->GetName()) {} + cFCONode(const cFCOName& name) : mpFCO(0), mpFCOName(&name) {} + cFCONode(const cFCONode& rhs) : mpFCO(rhs.mpFCO), mpFCOName(rhs.mpFCOName) {} + bool operator < (const cFCONode& rhs) const { if(mpFCOName) return (*mpFCOName < *rhs.mpFCOName); else return false; } + bool operator ==(const cFCONode& rhs) const { if(mpFCOName) return (*mpFCOName == *rhs.mpFCOName); else return false; } + }; + + std::set mFCOSet; + // this is what actually stores the iFCOs. +}; + +class cFCOIterImpl : public iFCOIter +{ + friend class cFCOSetImpl; + +public: + cFCOIterImpl(cFCOSetImpl* pSet); + cFCOIterImpl(const cFCOSetImpl* pSet); + + virtual void SeekBegin() const; + virtual bool Done() const; + virtual bool IsEmpty() const; + virtual void Next() const; + virtual const iFCO* FCO() const; + virtual iFCO* FCO(); + virtual bool SeekToFCO(const cFCOName& name) const; + + virtual void Remove(); + virtual void Remove() const; + virtual void DestroyIter() const; +private: + virtual ~cFCOIterImpl() ; + + cFCOSetImpl* mpSet; + mutable std::set::iterator mIter; + // the definition of a const iterator is not that its position cannot change, + // but that it cannot modify the set it is iterating over, hence the "mutable" +}; + + +#endif //__FCOSETIMPL_H + diff --git a/src/fco/fcosetimpl.h~ b/src/fco/fcosetimpl.h~ new file mode 100644 index 0000000..90d7c19 --- /dev/null +++ b/src/fco/fcosetimpl.h~ @@ -0,0 +1,128 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcosetimpl.h +// +// class cFCOSetImpl -- concrete implementation of an FCO set +// class cFCOIterImpl -- the iterator over the set +#ifndef __FCOSETIMPL_H +#define __FCOSETIMPL_H + +#ifndef __FCO_H +#include "fco.h" +#endif +#include "fconame.h" + +#ifndef __FCONAME_H +#include "fconame.h" +#endif + +class cFCOSetImpl : public iFCOSet +{ + friend class cFCOIterImpl; + DECLARE_TYPEDSERIALIZABLE() + +public: + cFCOSetImpl(); + cFCOSetImpl(const cFCOSetImpl& rhs); + virtual ~cFCOSetImpl(); + void operator=(const cFCOSetImpl& rhs); + + virtual const iFCOIter* Lookup(const cFCOName& name) const; + virtual iFCOIter* Lookup(const cFCOName& name); + virtual const iFCOIter* GetIter() const; + virtual iFCOIter* GetIter(); + virtual void Insert(iFCO* pFCO); + virtual void Clear(); + virtual bool IsEmpty() const; + virtual int Size() const { return mFCOSet.size(); }; + virtual void TraceContents(int dl = -1) const; + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +private: + void ReturnIter(const cFCOIterImpl* pIter) const; + // returns the iterator to its owner; the reciprocal action + // to Lookup() or GetIter(); called by the iterator when it is destroyed + + // class we store in the set below; it is a hack that allows us to + // look up iFCOs using cFCONames in a std::set + class cFCONode + { + public: + iFCO* mpFCO; + const cFCOName* mpFCOName; + + cFCONode() : mpFCO(0), mpFCOName(0) {} + cFCONode(iFCO* pFCO) : mpFCO(pFCO), mpFCOName(&pFCO->GetName()) {} + cFCONode(const cFCOName& name) : mpFCO(0), mpFCOName(&name) {} + cFCONode(const cFCONode& rhs) : mpFCO(rhs.mpFCO), mpFCOName(rhs.mpFCOName) {} + bool operator < (const cFCONode& rhs) const { if(mpFCOName) return (*mpFCOName < *rhs.mpFCOName); else return false; } + bool operator ==(const cFCONode& rhs) const { if(mpFCOName) return (*mpFCOName == *rhs.mpFCOName); else return false; } + }; + + std::set mFCOSet; + // this is what actually stores the iFCOs. +}; + +class cFCOIterImpl : public iFCOIter +{ + friend class cFCOSetImpl; + +public: + cFCOIterImpl(cFCOSetImpl* pSet); + cFCOIterImpl(const cFCOSetImpl* pSet); + + virtual void SeekBegin() const; + virtual bool Done() const; + virtual bool IsEmpty() const; + virtual void Next() const; + virtual const iFCO* FCO() const; + virtual iFCO* FCO(); + virtual bool SeekToFCO(const cFCOName& name) const; + + virtual void Remove(); + virtual void Remove() const; + virtual void DestroyIter() const; +private: + virtual ~cFCOIterImpl() ; + + cFCOSetImpl* mpSet; + mutable std::set::iterator mIter; + // the definition of a const iterator is not that its position cannot change, + // but that it cannot modify the set it is iterating over, hence the "mutable" +}; + + +#endif //__FCOSETIMPL_H + diff --git a/src/fco/fcosetimpl_t.cpp b/src/fco/fcosetimpl_t.cpp new file mode 100644 index 0000000..3c358c4 --- /dev/null +++ b/src/fco/fcosetimpl_t.cpp @@ -0,0 +1,150 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcosetimpl_t -- FCOSetImpl test driver + +#include "stdfco.h" +#include "fcosetimpl.h" +#include "fs/fsobject.h" +#include "core/debug.h" +#include "test/test.h" +#include "iterproxy.h" +#include "core/archive.h" +#include "core/serializerimpl.h" + +static void PrintIter(const iFCOIter* pIter, cDebug& d) +{ + TSTRING str; + for(; ! pIter->Done(); pIter->Next()) + { + str += pIter->FCO()->GetName().AsString().c_str(); + str += _T(" "); + } + d.TraceDebug(_T("%s\n"), str.c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// +// TestFCOSetImpl -- FCOSetImpl component test harness +/////////////////////////////////////////////////////////////////////////////// +void TestFCOSetImpl() +{ + cDebug d("TestFCOSetImpl()"); + d.TraceDebug("Entering...\n"); + + + iFCO* pFCO1 = new cFSObject(cFCOName(_T("fco1"))); + iFCO* pFCO2 = new cFSObject(cFCOName(_T("fco2"))); + iFCO* pFCO3 = new cFSObject(cFCOName(_T("fco3"))); + + cFCOSetImpl set; + set.Insert(pFCO1); + set.Insert(pFCO2); + set.Insert(pFCO3); + + // the set should have AddRef()ed, so I can release these now. + pFCO1->Release(); + pFCO2->Release(); + pFCO3->Release(); + + // let's iterate over the fcos + cIterProxy pit(set.GetIter()); + pit->SeekBegin(); + PrintIter(pit, d); + + // lookup a specific fco + cIterProxy pit2(set.Lookup(cFCOName(_T("fco2")))); + if(! (iFCOIter*)pit2) + { + d.TraceError("Lookup failed for fco2!\n"); + TEST(false); + } + + d.TraceDebug("Iterating from fco2 to end...\n"); + PrintIter(pit2, d); + + // Insert something + d.TraceDebug("Inserting dog...\n"); + pFCO1 = new cFSObject(cFCOName(_T("dog"))); + set.Insert(pFCO1); + pFCO1->Release(); + pit->SeekBegin(); + PrintIter(pit, d); + + // ...and then remove it + d.TraceDebug("Removing fco3\n"); + cIterProxy pit3(set.Lookup(cFCOName(_T("fco3")))); + if(! (iFCOIter*)pit3) + { + d.TraceError("Lookup failed for fco3!\n"); + TEST(false); + } + pit3->Remove(); + pit3->SeekBegin(); + PrintIter(pit3, d); + + // test operator= + cFCOSetImpl set2; + set2 = set; + pit = set2.GetIter(); + d.TraceDebug("Made a new set and set it equal to the first with operator=; printing out...\n"); + PrintIter(pit, d); + + // test IsEmpty + set.Clear(); + TEST(set.IsEmpty()); + + // test refrence counting... + d.TraceDebug("Set 1 was cleared out; printing set 2 to ensure ref counting worked\n"); + pit->SeekBegin(); + PrintIter(pit, d); + + // test serialization + cFCOSetImpl set3; + cMemoryArchive a; + cSerializerImpl writeSer(a, cSerializerImpl::S_WRITE); + writeSer.Init(); + set2.Write(&writeSer); + writeSer.Finit(); + a.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(a, cSerializerImpl::S_READ); + readSer.Init(); + set3.Read(&readSer); + readSer.Finit(); + d.TraceDebug("Serialized the set out and read it back in; this should be the same as above...\n"); + pit = set3.GetIter(); + PrintIter(pit, d); + + + d.TraceDebug("Leaving...\n"); + return; + +} + diff --git a/src/fco/fcosetws.h b/src/fco/fcosetws.h new file mode 100644 index 0000000..447d0de --- /dev/null +++ b/src/fco/fcosetws.h @@ -0,0 +1,138 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcosetws.h +// +// cFCOSetWS -- derived from cFCOSetImpl, this set is associated with a spec and +// for each insert, ASSERTs that the fco is contained in the spec. +// ws stands for either With Spec, With Sanity checking, or Warm Salamander +#ifndef __FCOSETWS_H +#define __FCOSETWS_H + +#ifndef __FCOSETIMPL_H +#include "fcosetimpl.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +#ifndef __FCOSPEC_H +#include "fcospec.h" +#endif + + +class cFCOSetWS : public cFCOSetImpl +{ +public: + cFCOSetWS(const iFCOSpec* pSpec); + // all FCOs that are inserted will be ASSERTed to be contained in this spec. + // the class will AddRef() the spec, so the sanity of this class can be subverted + // by changing the contents of the spec after this set is created + cFCOSetWS(const cFCOSetWS& rhs); + virtual ~cFCOSetWS(); + void operator=(const cFCOSetWS& rhs); + + void SetSpec(const iFCOSpec* pSpec); + // this may only be called if the set is empty (useful if you want to construct a + // set but you don't have the spec yet. The spec must be set before Insert() is called. + + virtual void Insert(iFCO* pFCO); +private: + const iFCOSpec* mpSpec; +}; + +//############################################################################# +// inline implementation +inline cFCOSetWS::cFCOSetWS(const iFCOSpec* pSpec) : + cFCOSetImpl(), + mpSpec(pSpec) +{ + if(mpSpec) + mpSpec->AddRef(); +} +inline cFCOSetWS::cFCOSetWS(const cFCOSetWS& rhs) : + cFCOSetImpl(rhs), + mpSpec(rhs.mpSpec) +{ + if(mpSpec) + mpSpec->AddRef(); +} + +inline cFCOSetWS::~cFCOSetWS() +{ + if(mpSpec) + mpSpec->Release(); +} + +inline void cFCOSetWS::operator=(const cFCOSetWS& rhs) +{ + mpSpec = rhs.mpSpec; + if(mpSpec) + mpSpec->AddRef(); + cFCOSetImpl::operator=(rhs); +} + +inline void cFCOSetWS::SetSpec(const iFCOSpec* pSpec) +{ + if(mpSpec) + mpSpec->Release(); + mpSpec = pSpec; + if(mpSpec) + mpSpec->AddRef(); +} + +inline void cFCOSetWS::Insert(iFCO* pFCO) +{ + // here is the only real work this class does! +#ifdef _DEBUG + // TODO -- note that this doesn't do any checking if the spec is NULL. I + // am not sure if this is the right thing to do or not. + if(mpSpec) + { + ASSERT(mpSpec->SpecContainsFCO(pFCO->GetName())); + + if(! mpSpec->SpecContainsFCO(pFCO->GetName())) + { + cDebug d("cFCOSetWS::Insert"); + d.TraceError("*** Insert of FCO %s not appropriate for spec %s\n", pFCO->GetName().AsString().c_str(), mpSpec->GetName().c_str()); + d.TraceError("*** Spec contents:\n"); + mpSpec->TraceContents(cDebug::D_ERROR); + } + } +#endif // _DEBUG + + cFCOSetImpl::Insert(pFCO); +} + + + +#endif //__FCOSETWS_H + diff --git a/src/fco/fcospec.cpp b/src/fco/fcospec.cpp new file mode 100644 index 0000000..2d8a09f --- /dev/null +++ b/src/fco/fcospec.cpp @@ -0,0 +1,82 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospec.cpp +// + +#include "stdfco.h" +#include "fcospec.h" +#include "fcospecimpl.h" +#include "core/serializer.h" +#include "core/errorgeneral.h" + +/////////////////////////////////////////////////////////////////////////////// +// class iFCOSpec +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// cDefaultSpecMask -- an implementation of iFCOSpecMask that implements the +// default mask +/////////////////////////////////////////////////////////////////////////////// +class cDefaultSpecMask : public iFCOSpecMask +{ +public: + virtual const TSTRING& GetName() const; + virtual bool Accept(const iFCO* pFCO) const; +private: + static const TSTRING mName; +}; + +const TSTRING cDefaultSpecMask::mName(_T("Default")); + +const TSTRING& cDefaultSpecMask::GetName() const +{ + return mName; +} + +bool cDefaultSpecMask::Accept(const iFCO* pFCO) const +{ + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// the single instance of an iFCOSpecMask that implements the default mask +/////////////////////////////////////////////////////////////////////////////// +static const cDefaultSpecMask defaultSpecMask; + +const iFCOSpecMask* iFCOSpecMask::GetDefaultMask() +{ + return &defaultSpecMask; +} + + diff --git a/src/fco/fcospec.h b/src/fco/fcospec.h new file mode 100644 index 0000000..f4b6f09 --- /dev/null +++ b/src/fco/fcospec.h @@ -0,0 +1,144 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospec.h +// +// iFCOSpec -- embodies a way to specify a set of FCOs +// iFCOSpecIter -- iterates over the FCOs that a spec maps to +// iFCOSpecMask -- classifies FCOs within an FCOSpec +#ifndef __FCOSPEC_H +#define __FCOSPEC_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __FCO_H +#include "fco.h" +#endif +#ifndef __TYPED_H +#include "typed.h" +#endif + +class iFCOSpecIter; +class iFCOSpecMask; +class cFCOPropVector; +class iFCOSpecHelper; + +class iFCOSpec : public iSerRefCountObj +{ +public: + virtual const TSTRING& GetName() const = 0; + // returns the name of this FCOSpec + virtual void SetName(const TSTRING& name) = 0; + // sets the spec's name + + virtual iFCOSpec* Clone() const = 0; + // makes a copy of this FCO. This method is needed because it is sometimes necessary + // for clients who only know about the base class interface to make copies of the object. + + virtual bool SpecContainsFCO(const cFCOName& name) const = 0; + // returns true if the fco is below the spec's start point and above its terminator. + + virtual const cFCOName& GetStartPoint() const = 0; + // Returns the name of the fco that is the "root node" for the FCO set that will + // be produced by the spec. + + virtual void SetStartPoint(const cFCOName& name) = 0; // throw (eError); + // sets the start point, as described in GetStartPoint() above. If a start point is added that is not + // above all the existing stop points, an eError is thrown. + + virtual void SetHelper( iFCOSpecHelper* pHelper ) = 0; + virtual const iFCOSpecHelper* GetHelper() const = 0; + // gets and sets the spec's helper class, which holds the start point and manages the spec's + // terminating criterion (stop points, etc.) + + virtual const cFCOPropVector& GetPropVector(const iFCOSpecMask* pFCOSpecMask) const = 0; + // returns the property vector associated with the given mask. Result is undefined + // if the mask isn't a part of the FCOSpec + virtual bool SetPropVector(const iFCOSpecMask* pMask, const cFCOPropVector& vector) = 0; + // sets the property vector associated with a specific mask. The pointer to the mask must + // be the same as one of the pointers that the spec contains (that is, the spec "owns" the + // masks, and the pointer passed into this method was acquired from GetSpecMask() below. + // Returns false if pMask isn't in the spec. + + virtual const iFCOSpecMask* GetSpecMask(const iFCO* pFCO) const = 0; + // returns the FCOSpecMask associated with the FCO that the iterator is + // pointing at + + const cFCOPropVector& GetPropVector(const iFCO* pFCO) const; + // inline convenience function that calls GetPropVector(GetSpecMask(pFCO)) + + // TODO -- add methods for manipulating the internal FCOSpecMask set + + /////////////////////////////// + // New for 2.1 + // + virtual bool ShouldStopDescent( const cFCOName& name ) const = 0; + // this method returns true if the named fco is not a part of the spec. More + // specifically, it only returns true for all of the fcos on the "border" + // between being in and out of the spec. This will assert that the name is + // below the start point. + + // + /////////////////////////////// + + virtual void TraceContents(int dl = -1) const {} + // traces the contents of the spec to wherever cDebug is pointing; not pure + // virtual so that one is not forced to implement it. + +}; + +class iFCOSpecMask +{ +public: + virtual const TSTRING& GetName() const = 0; + // return the name of this mask + + virtual bool Accept(const iFCO* pFCO) const = 0; + // returns true if the fco matches the criterion in the SpecMask + + static const iFCOSpecMask* GetDefaultMask(); + // returns the "default mask" that all iFCOSpecs must have. The default + // mask matches every FCO and is called "Default". There is no need to + // destroy the returned pointer +}; + +//############################################################################# +// inline implementation +inline const cFCOPropVector& iFCOSpec::GetPropVector(const iFCO* pFCO) const +{ + return GetPropVector(GetSpecMask(pFCO)); +} + + +#endif //__FCOSPEC_H + diff --git a/src/fco/fcospec_t.cpp b/src/fco/fcospec_t.cpp new file mode 100644 index 0000000..a3698eb --- /dev/null +++ b/src/fco/fcospec_t.cpp @@ -0,0 +1,52 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospec_t -- the fcospec test driver + +#include "stdfco.h" +#include "fcospec.h" +#include "core/debug.h" +#include + +using namespace std; + +void TestFCOSpec() +{ + cout << "Begin\tTestFCOSpec" << endl; + // all it seems I can test here is that the default mask works + const iFCOSpecMask* pDefMask = iFCOSpecMask::GetDefaultMask(); + ASSERT(pDefMask->GetName().compare(TSTRING(_T("Default"))) == 0); + iFCO* pf1 = (iFCO*)0xbad, *pf2 = (iFCO*)0xcab; + ASSERT( pDefMask->Accept(pf1) && pDefMask->Accept(pf2) ); + + cout << "End\tTestFCOSpec" << endl; + return; +} diff --git a/src/fco/fcospecattr.cpp b/src/fco/fcospecattr.cpp new file mode 100644 index 0000000..6801d1d --- /dev/null +++ b/src/fco/fcospecattr.cpp @@ -0,0 +1,95 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecattr.cpp +// + +#include "stdfco.h" +#include "fcospecattr.h" +#include "core/serializer.h" + +IMPLEMENT_SERREFCOUNT(cFCOSpecAttr, _T("cFCOSpecAttr"), 0, 1) + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecAttr::Read(iSerializer* pSerializer, int32 version) +{ + pSerializer->ReadString(mName); + pSerializer->ReadInt32(mSeverity); + + int32 size; + TSTRING str; + pSerializer->ReadInt32(size); + mEmailAddrs.clear(); + for(int i=0; i < size; i++) + { + pSerializer->ReadString(str); + mEmailAddrs.push_back(str); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecAttr::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteString(mName); + pSerializer->WriteInt32(mSeverity); + + pSerializer->WriteInt32(mEmailAddrs.size()); + std::list::const_iterator i; + for(i = mEmailAddrs.begin(); i != mEmailAddrs.end(); ++i) + pSerializer->WriteString(*i); +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecAttr::TraceContents(int dl) const +{ + cDebug d("cFCOSpecAttr::TraceContents"); + if(dl < 0) + dl = cDebug::D_DEBUG; + + d.Trace(dl,"--- cFCOSpecAttr ---\n"); + d.Trace(dl, "Name: %s Severity: %d\n", mName.c_str(), mSeverity); + d.Trace(dl, "Email addresses:\n"); + + std::list::const_iterator i; + for(i = mEmailAddrs.begin(); i != mEmailAddrs.end(); ++i) + { + d.Trace(dl, "\t%s\n", i->c_str()); + } +} + + diff --git a/src/fco/fcospecattr.h b/src/fco/fcospecattr.h new file mode 100644 index 0000000..c3fc3a9 --- /dev/null +++ b/src/fco/fcospecattr.h @@ -0,0 +1,185 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecattr.h +// +// cFCOSpecAttr -- class that holds integrity-check related fco spec attributes +#ifndef __FCOSPECATTR_H +#define __FCOSPECATTR_H + +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" +#endif +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __TYPES_H +#include "types.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +/////////////////////////////////////////////////////////////////////////////// +// cFCOSpecAttr +/////////////////////////////////////////////////////////////////////////////// +class cFCOSpecAttr : public iSerRefCountObj +{ +public: + cFCOSpecAttr(); + virtual ~cFCOSpecAttr(); + + /////////////////////// + // the attributes + /////////////////////// + const TSTRING& GetName() const; + void SetName(const TSTRING& name); + + int32 GetSeverity() const; + void SetSeverity(int32 s); + + int GetNumEmail() const; + void AddEmail(const TSTRING& str); + // adds an email address for report notification. This class makes no attempt + // to catch and prune identical entries in the email list. + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + void TraceContents(int dl = -1) const; + + DECLARE_SERREFCOUNT() +private: + cFCOSpecAttr (const cFCOSpecAttr& rhs); // not impl + void operator= (const cFCOSpecAttr& rhs); // not impl + + std::list mEmailAddrs; // the email addresses of people to be notified + TSTRING mName; // the name of the spec + int32 mSeverity; // the severity level + + friend class cFCOSpecAttrEmailIter; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOSpecAttrEmailIter +/////////////////////////////////////////////////////////////////////////////// +class cFCOSpecAttrEmailIter +{ +public: + cFCOSpecAttrEmailIter(const cFCOSpecAttr& attr); + ~cFCOSpecAttrEmailIter(); + + void SeekBegin() const; + bool Done() const; + bool IsEmpty() const; + void Next() const; + + const TSTRING& EmailAddress() const; +private: + const std::list& mSet; + mutable std::list::const_iterator mIter; +}; + + +//############################################################################# +// inline implementation +inline cFCOSpecAttr::cFCOSpecAttr() : + mName(_T("Unnamed")), + mSeverity(0) +{ +} +inline cFCOSpecAttr::~cFCOSpecAttr() +{ +} +inline const TSTRING& cFCOSpecAttr::GetName() const +{ + return mName; +} +inline void cFCOSpecAttr::SetName(const TSTRING& name) +{ + mName = name; +} +inline int32 cFCOSpecAttr::GetSeverity() const +{ + return mSeverity; +} +inline void cFCOSpecAttr::SetSeverity(int32 s) +{ + mSeverity = s; +} + +inline void cFCOSpecAttr::AddEmail(const TSTRING& str) +{ + mEmailAddrs.push_back(str); +} +inline int cFCOSpecAttr::GetNumEmail() const +{ + return mEmailAddrs.size(); +} + +/////////////// +// iterator +/////////////// +inline cFCOSpecAttrEmailIter::cFCOSpecAttrEmailIter(const cFCOSpecAttr& attr) : + mSet(attr.mEmailAddrs) +{ + mIter = mSet.begin(); +} + +inline cFCOSpecAttrEmailIter::~cFCOSpecAttrEmailIter() +{ +} +inline void cFCOSpecAttrEmailIter::SeekBegin() const +{ + mIter = mSet.begin(); +} +inline bool cFCOSpecAttrEmailIter::Done() const +{ + return (mIter == mSet.end()); +} +inline bool cFCOSpecAttrEmailIter::IsEmpty() const +{ + return mSet.empty(); +} +inline void cFCOSpecAttrEmailIter::Next() const +{ + mIter++; +} +inline const TSTRING& cFCOSpecAttrEmailIter::EmailAddress() const +{ + ASSERT(! Done()); + return *mIter; +} + + + +#endif //__FCOSPECATTR_H + diff --git a/src/fco/fcospecattr_t.cpp b/src/fco/fcospecattr_t.cpp new file mode 100644 index 0000000..de4ff40 --- /dev/null +++ b/src/fco/fcospecattr_t.cpp @@ -0,0 +1,87 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospecattr_t + +#include "stdfco.h" +#include "fcospecattr.h" +#include "test/test.h" +#include "core/archive.h" +#include "core/serializerimpl.h" + +static void TraceSpecAttr(const cFCOSpecAttr* pAttr, cDebug d) +{ + d.TraceDebug("--- Printing contents ---\n"); + d.TraceDebug(_T("Name: %s Severity: %d\n"), pAttr->GetName().c_str(), pAttr->GetSeverity()); + d.TraceDebug("Email addresses:\n"); + + cFCOSpecAttrEmailIter i(*pAttr); + for(i.SeekBegin(); ! i.Done(); i.Next()) + { + d.TraceDebug(_T("\t%s\n"), i.EmailAddress().c_str()); + } +} + +void TestFCOSpecAttr() +{ + cDebug d("TestFCOSpecAttr"); + d.TraceDebug("Entering\n"); + cFCOSpecAttr* pAttr = new cFCOSpecAttr; + + pAttr->SetName (_T("My Name")); d.TraceDebug("Setting Name = My Name\n"); + pAttr->SetSeverity (53); d.TraceDebug("Setting Severity = 53\n"); + pAttr->AddEmail (_T("dog@bark.com")); d.TraceDebug("Adding email = dog@bark.com\n"); + pAttr->AddEmail (_T("cow@moo.com")); d.TraceDebug("Adding email = cow@moo.com\n"); + pAttr->AddEmail (_T("cat@meow.com")); d.TraceDebug("Adding email = cat@meow.com\n"); + + // trace contents... + TraceSpecAttr(pAttr, d); + + // test serialization... + d.TraceDebug("Testing Serialization; next output should be the same as the previous\n"); + cMemoryArchive a; + cSerializerImpl s(a, cSerializerImpl::S_WRITE); + s.Init(); + pAttr->Write(&s); + s.Finit(); + a.Seek(0, cBidirArchive::BEGINNING); + cFCOSpecAttr* pNew = new cFCOSpecAttr; + cSerializerImpl s2(a, cSerializerImpl::S_READ); + s2.Init(); + pNew->Read(&s2); + s2.Finit(); + + // trace contents... + TraceSpecAttr(pNew, d); + + pNew->Release(); + pAttr->Release(); +} diff --git a/src/fco/fcospechelper.cpp b/src/fco/fcospechelper.cpp new file mode 100644 index 0000000..be43ea0 --- /dev/null +++ b/src/fco/fcospechelper.cpp @@ -0,0 +1,394 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospechelper.cpp +// + +#include "stdfco.h" +#include "fcospechelper.h" +#include "core/debug.h" +#include "core/serializer.h" +#include "twfactory.h" +#include "fconametranslator.h" + +//############################################################################# +// iFCOSpecHelper +//############################################################################# +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void iFCOSpecHelper::Read (iSerializer* pSerializer, int32 version) +{ + // read the start point + pSerializer->ReadObject(&mStartPoint); +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void iFCOSpecHelper::Write(iSerializer* pSerializer) const +{ + // write the start point + pSerializer->WriteObject(&mStartPoint); +} + + + +//############################################################################# +// cFCOSpecStopPointSet +//############################################################################# +IMPLEMENT_TYPEDSERIALIZABLE(cFCOSpecStopPointSet, _T("cFCOSpecStopPointSet"), 0, 1) + + +/////////////////////////////////////////////////////////////////////////////// +// cFCOSpecStopPointSet +/////////////////////////////////////////////////////////////////////////////// +cFCOSpecStopPointSet::cFCOSpecStopPointSet() +: mRecurseDepth( cFCOSpecStopPointSet::RECURSE_INFINITE ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// ContainsFCO +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecStopPointSet::ContainsFCO(const cFCOName& name) const +{ + // make sure name is at or below start point + cFCOName::Relationship rel = name.GetRelationship(GetStartPoint()); + if((rel != cFCOName::REL_BELOW) && (rel != cFCOName::REL_EQUAL)) + return false; + + // chack all the stop points + std::set::const_iterator itr; + for (itr = mStopPoints.begin(); itr != mStopPoints.end(); ++itr) + { + rel = name.GetRelationship(*itr); + if((rel == cFCOName::REL_BELOW) || (rel == cFCOName::REL_EQUAL)) + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetStartPoint +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecStopPointSet::SetStartPoint(const cFCOName& startPoint) +{ + cDebug d("cFCOSpecStopPointSet::SetStartPoint"); + + // make sure the start point is above all stop points... + std::set::iterator i; + for(i = mStopPoints.begin(); i != mStopPoints.end(); ++i) + { + if(i->GetRelationship(startPoint) != cFCOName::REL_BELOW) + { + TOSTRINGSTREAM str; + str << "Bad start point [" + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( startPoint ) + << "] added to spec with stop point " + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( *i ) + << std::ends; + + d.TraceError("%s\n", str.str().c_str()); + throw eSerializerInputStreamFmt(str.str().c_str()); + } + } + + // ok, it is acceptable to add this + inherited::SetStartPoint(startPoint); +} + +/////////////////////////////////////////////////////////////////////////////// +// ShouldStopDescent -- this returns true if we have just crossed the +// "boundary" between what is in and what is out of the spec's set. For +// StopPointSets, this means that the fco name matches a stop point +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecStopPointSet::ShouldStopDescent(const cFCOName& name) const +{ + cDebug d("cFCOSpecStopPointSet::ShouldStopDescent"); + // + // first, check the recurse depth... + // + if( GetRecurseDepth() != RECURSE_INFINITE ) + { + if( (name.GetSize() - mStartPoint.GetSize()) > GetRecurseDepth() ) + return true; + } + + + std::set::const_iterator i = mStopPoints.find(name); + return (i != mStopPoints.end()); +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecStopPointSet::TraceContents(int dl) const +{ + cDebug d("cFCOSpecStopPointSet::TraceContents"); + if(dl == -1) + dl = cDebug::D_DEBUG; + + d.Trace(dl, _T("Start Point:\t%s\n"), mStartPoint.AsString().c_str()); + for(std::set::const_iterator i = mStopPoints.begin(); + i != mStopPoints.end(); ++i) + { + d.Trace(dl, _T("Stop Point :\t%s\n"), i->AsString().c_str()); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Add +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecStopPointSet::Add(const cFCOName& name) +{ + cDebug d("cFCOSpecImpl::AddStopPoint"); + + // first, make sure this stop point is below the start point + if(name.GetRelationship(mStartPoint) != cFCOName::REL_BELOW) + { + d.TraceError("Attempt to add stop point that is not below start point!\n"); + d.TraceError("\tstart point = %s stop point = %s\n", mStartPoint.AsString().c_str(), name.AsString().c_str()); + + TOSTRINGSTREAM str; + str << "Attempt to add stop point that is not below start point!" + << " start point = " + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( mStartPoint ) + << " stop point = " + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( name ) + << std::ends; + + d.TraceError(_T("%s\n"), str.str().c_str()); + throw eSerializerInputStreamFmt(str.str().c_str()); + } + + std::set::iterator i; + for(i = mStopPoints.begin(); i != mStopPoints.end(); ) + { + cFCOName::Relationship rel = name.GetRelationship(*i); + switch(rel) + { + case cFCOName::REL_EQUAL: + d.TraceDebug(_T("Attempt to add stop point %s that already exists in spec %s\n"), name.AsString().c_str(), mStartPoint.AsString().c_str()); + return; + case cFCOName::REL_BELOW: + d.TraceDebug(_T("Attempt to add stop point %s to spec %s, but stop point %s already exists!\n"), + name.AsString().c_str(), mStartPoint.AsString().c_str(), i->AsString().c_str()); + return; + case cFCOName::REL_ABOVE: + // this stop point will replace the encountered stop point, so remove it! + d.TraceDebug(_T("Attempt to add stop point %s to spec %s, so removing stop point %s\n"), + name.AsString().c_str(), mStartPoint.AsString().c_str(), i->AsString().c_str()); + // we have to be careful we don't decrement past the beginning of the set! + if(i == mStopPoints.begin()) + { + mStopPoints.erase(i); + i = mStopPoints.begin(); + } + else + mStopPoints.erase(i++); + break; + + default: + i++; + } + } + + // finally, insert the name + mStopPoints.insert(name); +} + +/////////////////////////////////////////////////////////////////////////////// +// Clone +/////////////////////////////////////////////////////////////////////////////// +iFCOSpecHelper* cFCOSpecStopPointSet::Clone() const +{ + cFCOSpecStopPointSet* pNew = new cFCOSpecStopPointSet; + + pNew->mStartPoint = mStartPoint; + + std::set::const_iterator itr; + for (itr = mStopPoints.begin(); itr != mStopPoints.end(); ++itr) + { + pNew->Add(*itr); + } + + return pNew; +} + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecStopPointSet::Read (iSerializer* pSerializer, int32 version) +{ + // read the start point + //pSerializer->ReadObject(&mStartPoint); + inherited::Read(pSerializer, version); + + // read all the stop points + int32 size; + pSerializer->ReadInt32(size); + ASSERT(size >= 0); + for (int i = 0; i < size; ++i) + { + cFCOName fcoName; + pSerializer->ReadObject(&fcoName); + mStopPoints.insert(fcoName); + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecStopPointSet::Write(iSerializer* pSerializer) const +{ + // write the start point + //pSerializer->WriteObject(&mStartPoint); + inherited::Write(pSerializer); + + // write all the stop points + pSerializer->WriteInt32(mStopPoints.size()); + std::set::const_iterator itr; + for (itr = mStopPoints.begin(); itr != mStopPoints.end(); ++itr) + { + pSerializer->WriteObject(&(*itr)); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Compare +/////////////////////////////////////////////////////////////////////////////// +iFCOSpecHelper::CompareResult cFCOSpecStopPointSet::Compare(const iFCOSpecHelper* pRhs) const +{ + // if different types, order on mType address :-) + if(pRhs->GetType() != GetType()) + return ((&pRhs->GetType() < &GetType()) ? CMP_LT : CMP_GT); + + const cFCOSpecStopPointSet* pStopPtSet = static_cast(pRhs); + if(GetStartPoint() != pStopPtSet->GetStartPoint()) + return ((GetStartPoint() < pStopPtSet->GetStartPoint()) ? CMP_LT : CMP_GT); + + if(GetSize() != pStopPtSet->GetSize()) + return ((GetSize() < pStopPtSet->GetSize()) ? CMP_LT : CMP_GT); + + std::set::const_iterator myIter = mStopPoints.begin(), + rhsIter = pStopPtSet->mStopPoints.begin(); + for(; myIter != mStopPoints.end(); myIter++, rhsIter++) + { + if(*myIter != *rhsIter) + return ((*myIter < *rhsIter) ? CMP_LT : CMP_GT); + } + + // they must be equal! + return CMP_EQ; +} + +//############################################################################# +// cFCOSpecNoChildren +//############################################################################# +IMPLEMENT_TYPEDSERIALIZABLE(cFCOSpecNoChildren, _T("cFCOSpecNoChildren"), 0, 1) + +/////////////////////////////////////////////////////////////////////////////// +// ContainsFCO +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecNoChildren::ContainsFCO(const cFCOName& name) const +{ + return (name == GetStartPoint()); +} + +/////////////////////////////////////////////////////////////////////////////// +// Clone +/////////////////////////////////////////////////////////////////////////////// +iFCOSpecHelper* cFCOSpecNoChildren::Clone() const +{ + iFCOSpecHelper* pNew = new cFCOSpecNoChildren; + pNew->SetStartPoint(GetStartPoint()); + return pNew; +} + +/////////////////////////////////////////////////////////////////////////////// +// ShouldStopDescent +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecNoChildren::ShouldStopDescent(const cFCOName& name) const +{ + // we should stop for everything except the start point... + return ( name != GetStartPoint() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecNoChildren::Read (iSerializer* pSerializer, int32 version) +{ + inherited::Read(pSerializer, version); +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecNoChildren::Write(iSerializer* pSerializer) const +{ + inherited::Write(pSerializer); +} + +/////////////////////////////////////////////////////////////////////////////// +// Compare +/////////////////////////////////////////////////////////////////////////////// +iFCOSpecHelper::CompareResult cFCOSpecNoChildren::Compare(const iFCOSpecHelper* pRhs) const +{ + // if different types, order on mType address :-) + if(pRhs->GetType() != GetType()) + return ((&pRhs->GetType() < &GetType()) ? CMP_LT : CMP_GT); + + if(GetStartPoint() != pRhs->GetStartPoint()) + return ((GetStartPoint() < pRhs->GetStartPoint()) ? CMP_LT : CMP_GT); + + return CMP_EQ; +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecNoChildren::TraceContents(int dl) const +{ + cDebug d("cFCOSpecNoChildren::TraceContents"); + if(dl == -1) + dl = cDebug::D_DEBUG; + + d.Trace(dl, "Single FCO Spec (all children are stop points): %s\n", mStartPoint.AsString().c_str()); +} + + diff --git a/src/fco/fcospechelper.h b/src/fco/fcospechelper.h new file mode 100644 index 0000000..e1e0686 --- /dev/null +++ b/src/fco/fcospechelper.h @@ -0,0 +1,282 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospechelper.h +// +// iFCOSpecHelper-- object that manages a spec's start point and abstracts its +// stop criterion +#ifndef __FCOSPECHELPER_H +#define __FCOSPECHELPER_H + +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" +#endif +#ifndef __FCONAME_H +#include "fconame.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +#include + + +class iSerializer; + +/////////////////////////////////////////////////////////////////////////////// +// iFCOSpecHelper -- interface for managing a spec's start point and stop +// criterion +/////////////////////////////////////////////////////////////////////////////// +class iFCOSpecHelper : public iTypedSerializable +{ +public: + virtual void SetStartPoint(const cFCOName& startPoint);// throw (eError); + virtual const cFCOName& GetStartPoint() const; + // gets and sets the start point. SetStartPoint will throw an eError if the start point + // is inappropriate + + virtual bool ContainsFCO(const cFCOName& name) const = 0; + // returns true if the named fco is below the start point and "above" its terminating + // criterion + + virtual iFCOSpecHelper* Clone() const = 0; + // return a cloned copy of yourself; the clone will need to be deleted by the caller. + + virtual bool ShouldStopDescent(const cFCOName& name) const = 0; + // used by the iFCODataSource interface of iFCOSpec, this is called for each fco that is + // encountered. Really, ContainsFCO() could be used to reach the same ends, but + // this might/should be faster. + + virtual void Read (iSerializer* pSerializer, int32 version = 0); + virtual void Write(iSerializer* pSerializer) const; + // these just serialize the start point. + + enum CompareResult + { + CMP_LT = -1, + CMP_EQ = 0, + CMP_GT = 1 + }; + virtual CompareResult Compare(const iFCOSpecHelper* pRhs) const = 0; + // these are needed to define an ordering of specs. + + virtual void TraceContents(int dl = -1) const {} + + virtual ~iFCOSpecHelper() {} +protected: + cFCOName mStartPoint; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOSpecStopPoints -- a spec helper that uses a set of stop points. +// to determine where the spec ends. +// NOTE -- stop points are stored internally in an order defined by cFCOName::operator< +// All iterations over the stop points will be in this order. +// +// This class also keeps track of a "maximum recurse depth", where all +// calls to ShouldStopDescent() return true when the name is more than +// the maximum depth below the start point. +/////////////////////////////////////////////////////////////////////////////// +class cFCOSpecStopPointSet : public iFCOSpecHelper +{ +public: + cFCOSpecStopPointSet(); + + virtual void SetStartPoint(const cFCOName& startPoint); + virtual bool ContainsFCO(const cFCOName& name) const; + virtual bool ShouldStopDescent(const cFCOName& name) const ; + virtual void TraceContents(int dl= -1) const; + virtual iFCOSpecHelper* Clone() const; + + int GetSize() const; + // returns the number of stop points this contains + virtual void Clear(); + // clears the set of stop points. + virtual void Add(const cFCOName& name); // throw(eError) + // adds a stop point. Stop points may be removed and iterated through using + // the iterator below. + // If the stop point is above or below any existing stop points, the "lower" stop + // point will be replaced with the higher one. Thus, at any given time, + // all stop points are unrelated (retrun REL_UNRELATED from cFCOName::GetRelation) + + // + // recurse depth + // + enum { RECURSE_INFINITE = -1 }; + void SetRecurseDepth( int depth ) { mRecurseDepth = depth; } + int GetRecurseDepth() const { return mRecurseDepth; } + // gets and sets the maximum recurse depth. If a name passed to ShouldStopDescent() is deeper than + // the maximum recurse depth, true is returned. For example, if there are no stop points and the + // start point is /etc, if the recurse depth is 1, then /etc/dog will be processed but /etc/dog/bark + // will not. RECURSE_INFINITE can be passed in to indicate there is no maximum recurse depth. + + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); + virtual void Write(iSerializer* pSerializer) const; + + virtual CompareResult Compare(const iFCOSpecHelper* pRhs) const; + + DECLARE_TYPEDSERIALIZABLE() + + virtual ~cFCOSpecStopPointSet() {} +protected: + std::set mStopPoints; + int mRecurseDepth; + + friend class cFCOSpecStopPointIter; + typedef iFCOSpecHelper inherited; +}; + +class cFCOSpecStopPointIter +{ +public: + cFCOSpecStopPointIter(cFCOSpecStopPointSet& set); + + void SeekBegin() const; + // seeks to the beginning of the stop point list + bool Done() const; + // returns true if the iterator has gone past the end of the set + bool IsEmpty() const; + // is the set empty? + void Next() const; + // seek to the next element in the set + + const cFCOName& StopPoint() const; + const cFCOName& StopPoint(); + // methods for getting the StopPoint that the iterator is currently pointing at + + void Remove(); + // removes the fco pointed to by the iter. Behavior is undefined if the set is empty. + // after the erase, the iterator points to the next element in the list +private: + mutable std::set::iterator mIter; + std::set& mSet; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOSpecNoChildren -- an iFCOSpecHelper that maps to a single FCO -- the +// start point +/////////////////////////////////////////////////////////////////////////////// +class cFCOSpecNoChildren : public iFCOSpecHelper +{ +public: + virtual bool ContainsFCO(const cFCOName& name) const; + virtual iFCOSpecHelper* Clone() const; + virtual bool ShouldStopDescent(const cFCOName& name) const; + virtual void Read (iSerializer* pSerializer, int32 version = 0); + virtual void Write(iSerializer* pSerializer) const; + virtual CompareResult Compare(const iFCOSpecHelper* pRhs) const; + virtual void TraceContents(int dl = -1) const; + + DECLARE_TYPEDSERIALIZABLE() + + typedef iFCOSpecHelper inherited; +}; + +//############################################################################# +// inline implementation +//############################################################################# + +////////////////////////// +// iFCOSpecHelper +////////////////////////// +inline void iFCOSpecHelper::SetStartPoint(const cFCOName& startPoint) +{ + mStartPoint = startPoint; +} + +inline const cFCOName& iFCOSpecHelper::GetStartPoint() const +{ + return mStartPoint; +} + +////////////////////////// +// cFCOSpecStopPointSet +////////////////////////// +inline int cFCOSpecStopPointSet::GetSize() const +{ + return mStopPoints.size(); +} + +inline void cFCOSpecStopPointSet::Clear() +{ + mStopPoints.clear(); +} + +////////////////////////// +// cFCOSpecStopPointIter +////////////////////////// +inline cFCOSpecStopPointIter::cFCOSpecStopPointIter(cFCOSpecStopPointSet& set) : + mSet(set.mStopPoints) +{ + mIter = mSet.begin(); +} +inline void cFCOSpecStopPointIter::SeekBegin() const +{ + mIter = mSet.begin(); +} + +inline bool cFCOSpecStopPointIter::Done() const +{ + return (mIter == mSet.end()); +} + +inline bool cFCOSpecStopPointIter::IsEmpty() const +{ + return (mSet.size() == 0); +} + +inline void cFCOSpecStopPointIter::Next() const +{ + mIter++; +} + +inline void cFCOSpecStopPointIter::Remove() +{ + ASSERT(! Done()); + mSet.erase(mIter++); +} + +inline const cFCOName& cFCOSpecStopPointIter::StopPoint() const +{ + ASSERT(! Done()); + return (*mIter); +} + +inline const cFCOName& cFCOSpecStopPointIter::StopPoint() +{ + ASSERT(! Done()); + return (*mIter); +} + +#endif //__FCOSPECHELPER_H + diff --git a/src/fco/fcospechelper_t.cpp b/src/fco/fcospechelper_t.cpp new file mode 100644 index 0000000..ad2d8fb --- /dev/null +++ b/src/fco/fcospechelper_t.cpp @@ -0,0 +1,131 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospechelper_t.cpp + +#include "stdfco.h" +#include "fcospechelper.h" +#include "test/test.h" +#include "core/error.h" +#include "core/serializerimpl.h" +#include "core/archive.h" + +void TestFCOSpecHelper() +{ + cDebug d("TestFCOSpecHelper"); + d.TraceDebug("Entering...\n"); + + // test the start and stop point fringe cases... + d.TraceDebug("Testing start and stop point stuff...\n"); + cFCOSpecStopPointSet* pSet3 = new cFCOSpecStopPointSet; + pSet3->SetStartPoint(cFCOName(_T("/etc"))); d.TraceDebug("*** Added start point /etc\n"); + pSet3->Add(cFCOName(_T("/etc/dog/bark"))); d.TraceDebug("*** Added stop point /etc/dog/bark\n"); + pSet3->Add(cFCOName(_T("/etc/dog/pant"))); d.TraceDebug("*** Added stop point /etc/dog/pant\n\n"); + pSet3->Add(cFCOName(_T("/etc/cat/meow"))); d.TraceDebug("*** Added stop point /etc/cat/meow\n"); + pSet3->TraceContents(); + pSet3->Add(cFCOName(_T("/etc/dog"))); d.TraceDebug("*** Added stop point /etc/dog\n"); + pSet3->Add(cFCOName(_T("/etc/cat/purr"))); d.TraceDebug("*** Added stop point /etc/cat/purr\n"); + pSet3->Add(cFCOName(_T("/etc/cat/purr/loud"))); d.TraceDebug("*** Added stop point /etc/cat/purr/loud\n"); + pSet3->TraceContents(); + pSet3->Add(cFCOName(_T("/etc/dog"))); d.TraceDebug("*** Added stop point /etc/dog\n"); + try + { + pSet3->Add(cFCOName(_T("/var/spool"))); d.TraceDebug("*** Added stop point /var/spool\n"); + } + catch(eError& e) + { + d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str()); + } + try + { + pSet3->SetStartPoint(cFCOName(_T("/var"))); d.TraceDebug("*** Added start point /var\n"); + } + catch(eError& e) + { + d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str()); + } + try + { + pSet3->SetStartPoint(cFCOName(_T("/"))); d.TraceDebug("*** Added start point /\n"); + } + catch(eError& e) + { + d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str()); + } + pSet3->TraceContents(); + + // test SpecContainsFCO() + cFCOSpecStopPointSet* pSet4 = new cFCOSpecStopPointSet; + pSet4->SetStartPoint(cFCOName(_T("/etc"))); + pSet4->Add(cFCOName(_T("/etc/dog"))); + pSet4->Add(cFCOName(_T("/etc/cat/meow"))); + TEST( pSet4->ContainsFCO( cFCOName(_T("/etc/frog")))); + TEST( pSet4->ContainsFCO( cFCOName(_T("/etc/cat/paw")))); + TEST(! pSet4->ContainsFCO( cFCOName(_T("/etc/dog")))); + TEST(! pSet4->ContainsFCO( cFCOName(_T("/var/spool/mail")))); + TEST(! pSet4->ContainsFCO( cFCOName(_T("/etc/dog/bark")))); + + // test the All Children Stop Points case + cFCOSpecNoChildren noChildren; + noChildren.SetStartPoint(cFCOName(_T("/etc"))); + TEST( noChildren.ContainsFCO( cFCOName(_T("/etc")))); + TEST(! noChildren.ContainsFCO( cFCOName(_T("/etc/frog")))); + + // TODO -- test Compare() + + // test serialization + // test serialization + cMemoryArchive a; + cSerializerImpl s(a, cSerializerImpl::S_WRITE); + s.Init(); + s.WriteObjectDynCreate(pSet3); + s.WriteObjectDynCreate(&noChildren); + s.Finit(); + a.Seek(0, cBidirArchive::BEGINNING); + + iFCOSpecHelper* pHelp1, *pHelp2; + cSerializerImpl s2(a, cSerializerImpl::S_READ); + s2.Init(); + pHelp1 = (iFCOSpecHelper*)s2.ReadObjectDynCreate(); + pHelp2 = (iFCOSpecHelper*)s2.ReadObjectDynCreate(); + s2.Finit(); + + TEST(pHelp1->Compare(pSet3) == iFCOSpecHelper::CMP_EQ); + TEST(pHelp2->Compare(&noChildren) == iFCOSpecHelper::CMP_EQ); + TEST(pHelp1->Compare(&noChildren) != iFCOSpecHelper::CMP_EQ); + TEST(pHelp2->Compare(pSet3) != iFCOSpecHelper::CMP_EQ); + + + delete pSet3; + delete pSet4; + delete pHelp1; + delete pHelp2; +} diff --git a/src/fco/fcospecimpl.cpp b/src/fco/fcospecimpl.cpp new file mode 100644 index 0000000..1a9d8ee --- /dev/null +++ b/src/fco/fcospecimpl.cpp @@ -0,0 +1,225 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecimpl.cpp +// + +#include "stdfco.h" +#include "fcospecimpl.h" +#include "core/debug.h" +#include "core/serializer.h" +#include "iterproxy.h" +#include "fcospechelper.h" +#include "core/errorutil.h" + +#ifdef _DEBUG +int gFCOSpecImplCreated = 0; +int gFCOSpecImplDestroyed = 0; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// ctor and dtor +/////////////////////////////////////////////////////////////////////////////// +cFCOSpecImpl::cFCOSpecImpl(const TSTRING& name, void* pSrc, iFCOSpecHelper* pHelper) : + mName(name), + mpHelper(pHelper) +{ +#ifdef _DEBUG + ++gFCOSpecImplCreated; + cDebug d("cFCOSpecImpl::cFCOSpecImpl()"); + d.TraceDetail("Allocated cFCOSpecImpl(%p) creat=%d dest=%d\n", this, gFCOSpecImplCreated, gFCOSpecImplDestroyed); +#endif +} + +cFCOSpecImpl::cFCOSpecImpl() : + mName(_T("Unnamed_FCOSpecImpl")), + mpHelper(0) +{ +#ifdef _DEBUG + ++gFCOSpecImplCreated; + cDebug d("cFCOSpecImpl::cFCOSpecImpl()"); + d.TraceDetail("Allocated cFCOSpecImpl(%p) creat=%d dest=%d\n", this, gFCOSpecImplCreated, gFCOSpecImplDestroyed); +#endif +} + +cFCOSpecImpl::cFCOSpecImpl(const cFCOSpecImpl& rhs) : + mpHelper(0) +{ + *this = rhs; +#ifdef _DEBUG + ++gFCOSpecImplCreated; + cDebug d("cFCOSpecImpl::cFCOSpecImpl()"); + d.TraceDetail("Allocated cFCOSpecImpl(%p) creat=%d dest=%d\n", this, gFCOSpecImplCreated, gFCOSpecImplDestroyed); +#endif +} + +cFCOSpecImpl::~cFCOSpecImpl() +{ +#ifdef _DEBUG + ++gFCOSpecImplDestroyed; + cDebug d("cFCOSpecImpl::cFCOSpecImpl()"); + d.TraceDetail("Deleted cFCOSpecImpl(%p) creat=%d dest=%d\n", this, gFCOSpecImplCreated, gFCOSpecImplDestroyed); +#endif + + delete mpHelper; +} + +IMPLEMENT_SERREFCOUNT(cFCOSpecImpl, _T("cFCOSpecImpl"), 0, 1); + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecImpl::operator=(const cFCOSpecImpl& rhs) +{ + mName = rhs.mName; + mPropVector = rhs.mPropVector; + mpHelper = rhs.mpHelper ? rhs.mpHelper->Clone() : 0; +} +/////////////////////////////////////////////////////////////////////////////// +// Clone -- make a copy of this spec +/////////////////////////////////////////////////////////////////////////////// +iFCOSpec* cFCOSpecImpl::Clone() const +{ + cFCOSpecImpl* pNewSpec = new cFCOSpecImpl(mName); + *pNewSpec = *this; + return pNewSpec; +} + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents -- debug output of this object's contents +/////////////////////////////////////////////////////////////////////////////// +void cFCOSpecImpl::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFCOSpecImpl::TraceContents"); + d.Trace(dl, _T("FCOSpecImpl :\t%s\n"), mName.c_str()); + mPropVector.TraceContents(dl); + if(mpHelper) + mpHelper->TraceContents(dl); + else + d.Trace(dl, _T("\n") ); + + // NOTE -- tracing out the data source associated with this spec has no + // real value -- mdb +} + +const TSTRING& cFCOSpecImpl::GetName() const +{ + return mName; +} + +void cFCOSpecImpl::SetName(const TSTRING& name) +{ + mName = name; +} + +const cFCOName& cFCOSpecImpl::GetStartPoint() const +{ + ASSERT(mpHelper != 0); + return mpHelper->GetStartPoint(); +} + +void cFCOSpecImpl::SetStartPoint (const cFCOName& name) +{ + cDebug d("cFCOSpecImpl::SetStartPoint"); + + ASSERT(mpHelper != 0); + mpHelper->SetStartPoint(name); +} + +const cFCOPropVector& cFCOSpecImpl::GetPropVector(const iFCOSpecMask* pFCOSpecMask) const +{ + // NOTE: for now, there will only be one property vector associated with a given specifier + return mPropVector; +} + +bool cFCOSpecImpl::SetPropVector(const iFCOSpecMask* pMask, const cFCOPropVector& vector) +{ + // for now, the default mask is the only mask the spec has. + if(pMask != iFCOSpecMask::GetDefaultMask()) + return false; + + mPropVector = vector; + return true; +} + +const iFCOSpecMask* cFCOSpecImpl::GetSpecMask(const iFCO* pFCO) const +{ + // for now, I will just return the default property mask + return iFCOSpecMask::GetDefaultMask(); +} + + +void cFCOSpecImpl::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("FS Spec Read"))); + + pSerializer->ReadString(mName); + mPropVector.Read(pSerializer); + + // read the helper + mpHelper = (iFCOSpecHelper*)pSerializer->ReadObjectDynCreate(); +} + +void cFCOSpecImpl::Write(iSerializer* pSerializer) const +{ + ASSERT(mpHelper != 0); + + pSerializer->WriteString(mName); + mPropVector.Write(pSerializer); + + pSerializer->WriteObjectDynCreate(mpHelper); +} + +/////////////////////////////////////////////////////////////////////////////// +// SpecContainsFCO +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecImpl::SpecContainsFCO(const cFCOName& name) const +{ + ASSERT(mpHelper != 0); + + return mpHelper->ContainsFCO(name); +} + +/////////////////////////////////////////////////////////////////////////////// +// ShouldStopDescent +/////////////////////////////////////////////////////////////////////////////// +bool cFCOSpecImpl::ShouldStopDescent( const cFCOName& name ) const +{ + ASSERT(mpHelper != 0); + return mpHelper->ShouldStopDescent( name ); +} + + diff --git a/src/fco/fcospecimpl.h b/src/fco/fcospecimpl.h new file mode 100644 index 0000000..61981c8 --- /dev/null +++ b/src/fco/fcospecimpl.h @@ -0,0 +1,123 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecimpl.h +// +// class cFCOSpecImpl -- an implementation of iFCOSpec for file systems +#ifndef __FCOSPECIMPL_H +#define __FCOSPECIMPL_H + +#ifndef __FCOSPEC_H +#include "fcospec.h" +#endif +#ifndef __FCOPROPVECTOR_H +#include "fcopropvector.h" +#endif +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +#include + +class cErrorBucket; +class iFCOSpecHelper; +/////////////////////////////////////////////////////////////////////// +// NOTE: it is interesting that there is nothing about this class that +// is specific to files; it could potentially be used with other FCOs, +// so maybe its name should be changed to cFCOSpecImpl or something +// like that -- mdb +/////////////////////////////////////////////////////////////////////// +class cFCOSpecImpl : public iFCOSpec +{ + DECLARE_SERREFCOUNT() +public: + // TODO -- remove the iFCODataSource from the ctor; I am doing nothing with it right now and + // didn't change it simply because I don't want to touch 1000 files updateing the creation + // parameters... 28 jan mdb + // + cFCOSpecImpl(const TSTRING& name, /* const iFCODataSource* */ void* pSrc = 0, iFCOSpecHelper* pHelper = NULL); + // the spec will delegate fco creation to pSrc as needed. It is OK to pass NULL as the data + // source, but it must be set before this spec can be used. + // the spec will delete whatever helper it contains when it is destroyed + cFCOSpecImpl(const cFCOSpecImpl& rhs); + cFCOSpecImpl(); + void operator=(const cFCOSpecImpl& rhs); + + // from iFCOSpec + virtual bool SpecContainsFCO (const cFCOName& name) const; + virtual const TSTRING& GetName () const ; + virtual void SetName (const TSTRING& name); + virtual iFCOSpec* Clone () const; + virtual const cFCOName& GetStartPoint () const ; + virtual void SetStartPoint (const cFCOName& name) ; // throw (eError); + virtual const cFCOPropVector& GetPropVector (const iFCOSpecMask* pFCOSpecMask) const ; + virtual bool SetPropVector (const iFCOSpecMask* pMask, const cFCOPropVector& vector); + virtual const iFCOSpecMask* GetSpecMask (const iFCO* pFCO) const ; + virtual void TraceContents (int dl = -1) const; + virtual bool ShouldStopDescent( const cFCOName& name ) const ; + + virtual void SetHelper(iFCOSpecHelper* pHelper); + virtual const iFCOSpecHelper* GetHelper() const; + // helper manipulation; note that the spec will delete whatever helper it contains when it is destroyed, + // but it will not delete the current helper when SetHelper() is called. + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + + virtual ~cFCOSpecImpl(); + // only destroy with Release(). Don't create on the stack. +private: + + TSTRING mName; + cFCOPropVector mPropVector; + iFCOSpecHelper* mpHelper; +}; + +//############################################################################# +// inline impl +//############################################################################# +inline void cFCOSpecImpl::SetHelper(iFCOSpecHelper* pHelper) +{ + mpHelper = pHelper; +} + +inline const iFCOSpecHelper* cFCOSpecImpl::GetHelper() const +{ + ASSERT(mpHelper != 0); + return mpHelper; +} + + +#endif //__FCOSPECIMPL_H + diff --git a/src/fco/fcospeclist.cpp b/src/fco/fcospeclist.cpp new file mode 100644 index 0000000..fa2c9d6 --- /dev/null +++ b/src/fco/fcospeclist.cpp @@ -0,0 +1,295 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospeclist.cpp +// +// cFCOSpecList -- a list of iFCOSpec's with in a well defined order. +/////////////////////////////////////////////////////////////////////////////// + +#include "stdfco.h" +#include "fcospeclist.h" +#include "fcospecutil.h" +#include "core/serializer.h" +#include "core/debug.h" +#include "core/errorutil.h" + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOSpecList-- a list of iFCOSpec's with a well defined order. +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOSpecList, _T("cFCOSpecList"), 0, 1) + +cFCOSpecList::cFCOSpecList() +{ +} + +cFCOSpecList::~cFCOSpecList() +{ + Clear(); +} + +void cFCOSpecList::Clear() +{ + std::list::iterator itr; + + for (itr = mAddedList.begin(); itr != mAddedList.end(); itr++) + { + itr->first->Release(); + itr->second->Release(); + } + + mCanonicalList.clear(); + mAddedList.clear(); +} + +bool cFCOSpecList::IsEmpty() const +{ + return mAddedList.empty(); +} + +int cFCOSpecList::Size() const +{ + return mAddedList.size(); +} + +const cFCOSpecList& cFCOSpecList::operator = (const cFCOSpecList& rhs) +{ + Clear(); + + cFCOSpecListAddedIter itr(rhs); + + for (itr.SeekBegin(); !itr.Done(); itr.Next()) + { + Add(itr.Spec(), itr.Attr()); + } + + return *this; +} + +void cFCOSpecList::Add(iFCOSpec* pSpec, cFCOSpecAttr* pAttr) +{ + std::list::iterator itr; + pSpec->AddRef(); + if(pAttr == 0) + pAttr = new cFCOSpecAttr; + else + pAttr->AddRef(); + for (itr = mCanonicalList.begin(); ; ++itr) + { + if (itr == mCanonicalList.end() || + iFCOSpecUtil::FCOSpecLessThan(*pSpec, *itr->first)) + { + mCanonicalList.insert(itr, PairType(pSpec, pAttr)); + mAddedList.push_back(PairType(pSpec, pAttr)); + break; + } + } +} + +iFCOSpec* cFCOSpecList::Lookup(iFCOSpec* pSpec) const +{ + std::list::iterator itr; + for (itr = mCanonicalList.begin(); itr != mCanonicalList.end(); ++itr) + if (itr->first == pSpec) + { + pSpec->AddRef(); + return itr->first; + } + + for (itr = mCanonicalList.begin(); itr != mCanonicalList.end(); ++itr) + if (iFCOSpecUtil::FCOSpecEqual(*pSpec, *itr->first)) + { + itr->first->AddRef(); + return itr->first; + } + + return NULL; +} + +void cFCOSpecList::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("FCO Spec List"))); + + Clear(); + + int i; + int32 size; + pSerializer->ReadInt32(size); + + for (i = 0; i < size; ++i) + { + iFCOSpec* pReadInSpec = static_cast (pSerializer->ReadObjectDynCreate()); + cFCOSpecAttr* pSpecAttr = static_cast(pSerializer->ReadObjectDynCreate()); + Add(pReadInSpec, pSpecAttr); + pReadInSpec->Release(); // Add() will increase the ref count by 1 + pSpecAttr->Release(); + } +} + +void cFCOSpecList::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32(Size()); + + cFCOSpecListAddedIter itr(*this); + for (itr.SeekBegin(); !itr.Done(); itr.Next()) + { + pSerializer->WriteObjectDynCreate(itr.Spec()); + pSerializer->WriteObjectDynCreate(itr.Attr()); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOSpecListAddedIter -- iterate using the order in which items were +// added to this list. +/////////////////////////////////////////////////////////////////////////////// + +cFCOSpecListAddedIter::cFCOSpecListAddedIter(const cFCOSpecList& list) +{ + mpSpecList = (cFCOSpecList*)&list; + mIter = mpSpecList->mAddedList.begin(); +} + +cFCOSpecListAddedIter::~cFCOSpecListAddedIter() +{ +} + +void cFCOSpecListAddedIter::SeekBegin() const +{ + mIter = mpSpecList->mAddedList.begin(); +} + +bool cFCOSpecListAddedIter::Done() const +{ + return mIter == mpSpecList->mAddedList.end(); +} + +bool cFCOSpecListAddedIter::IsEmpty() const +{ + return mpSpecList->mAddedList.empty(); +} + +void cFCOSpecListAddedIter::Next() const +{ + ++mIter; +} + +const iFCOSpec* cFCOSpecListAddedIter::Spec() const +{ + return mIter->first; +} + +iFCOSpec* cFCOSpecListAddedIter::Spec() +{ + return mIter->first; +} +const cFCOSpecAttr* cFCOSpecListAddedIter::Attr() const +{ + return mIter->second; +} +cFCOSpecAttr* cFCOSpecListAddedIter::Attr() +{ + return mIter->second; +} + +void cFCOSpecListAddedIter::Remove() +{ + ASSERT(! Done()); + + // the tricky part is finding the spec in the other list... + std::list::iterator i; + for(i = mpSpecList->mCanonicalList.begin(); i != mpSpecList->mCanonicalList.end(); i++) + { + if(i->first == mIter->first) + break; + } + ASSERT(i != mpSpecList->mCanonicalList.end()); + + // now to do the deleteing! + mIter = mpSpecList->mAddedList.erase(mIter); + mpSpecList->mCanonicalList.erase(i); +} + + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOSpecListCanonicalIter -- iterate using the order in which items were +// added to this list. +/////////////////////////////////////////////////////////////////////////////// + +cFCOSpecListCanonicalIter::cFCOSpecListCanonicalIter(const cFCOSpecList& list) +{ + mpSpecList = (cFCOSpecList*)&list; + mIter = mpSpecList->mCanonicalList.begin(); +} + +cFCOSpecListCanonicalIter::~cFCOSpecListCanonicalIter() +{ +} + +void cFCOSpecListCanonicalIter::SeekBegin() const +{ + mIter = mpSpecList->mCanonicalList.begin(); +} + +bool cFCOSpecListCanonicalIter::Done() const +{ + return mIter == mpSpecList->mCanonicalList.end(); +} + +bool cFCOSpecListCanonicalIter::IsEmpty() const +{ + return mpSpecList->mCanonicalList.empty(); +} + +void cFCOSpecListCanonicalIter::Next() const +{ + ++mIter; +} + +const iFCOSpec* cFCOSpecListCanonicalIter::Spec() const +{ + return mIter->first; +} + +iFCOSpec* cFCOSpecListCanonicalIter::Spec() +{ + return mIter->first; +} +const cFCOSpecAttr* cFCOSpecListCanonicalIter::Attr() const +{ + return mIter->second; +} +cFCOSpecAttr* cFCOSpecListCanonicalIter::Attr() +{ + return mIter->second; +} + diff --git a/src/fco/fcospeclist.h b/src/fco/fcospeclist.h new file mode 100644 index 0000000..590a16f --- /dev/null +++ b/src/fco/fcospeclist.h @@ -0,0 +1,159 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospeclist.h +// +// cFCOSpecList -- a list of iFCOSpec's with in a well defined order. + +#ifndef __FCOSPECLIST_H +#define __FCOSPECLIST_H + +#ifndef __FCOSPEC_H +#include "fcospec.h" +#endif +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif +#ifndef __FCOSPECATTR_H +#include "fcospecattr.h" +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOSpecList -- A list of iFCOSpec's with an optimized lookup method +// and preservation of order of addition of items. The optimized lookup +// is useful because we will want to look up specs quickly. Preserving +// the order in which items were added is useful because we will use +// cFCOSpecList's in the report and database were we wish to use the +// added order of the list to match to other lists. +/////////////////////////////////////////////////////////////////////////////// + +class cFCOSpecList : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + + friend class cFCOSpecListCanonicalIter; + friend class cFCOSpecListAddedIter; +public: + cFCOSpecList(); + cFCOSpecList(const cFCOSpecList& rhs); + virtual ~cFCOSpecList(); + + const cFCOSpecList& operator = (const cFCOSpecList& rhs); + + void Clear(); + // Clear the list of specs, deleting them all + + bool IsEmpty() const; + int Size() const; + + void Add(iFCOSpec* pSpec, cFCOSpecAttr* pAttr = 0); + // Add iFCOSpec to list. The objects will be AddRef()ed by the list + // and Release()d on destruction. If pAttr == NULL, then an empty + // attribute list will be created and associated with the spec. + + iFCOSpec* Lookup(iFCOSpec* pSpec) const; + // Search the list a spec that matches pSpec. This search is fairly + // low cost if pSpec points to an actual spec in this list. Otherwise + // string compares must be done to determine the result. Returns + // NULL if it is NOT in the list, otherwise a pointer to the object in + // this list that matches pSpec. Either way, if non-null is returned, the + // object was AddRef()ed + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + typedef std::pair PairType; + + mutable std::list mAddedList; // list in added order + mutable std::list mCanonicalList; // list in well defined order +}; + +class cFCOSpecListAddedIter +{ +public: + cFCOSpecListAddedIter(const cFCOSpecList& list); + ~cFCOSpecListAddedIter(); + + void SeekBegin() const; + bool Done() const; + bool IsEmpty() const; + void Next() const; + void Remove(); + // removes the node the iterator is currently pointing at. + // asserts !Done() and moves the iterator to the next node, + // or to the end if it is the last node. + + const iFCOSpec* Spec() const; + iFCOSpec* Spec(); + const cFCOSpecAttr* Attr() const; + cFCOSpecAttr* Attr(); + +protected: + cFCOSpecList* mpSpecList; + + mutable std::list::iterator mIter; +}; + +class cFCOSpecListCanonicalIter +{ +public: + cFCOSpecListCanonicalIter(const cFCOSpecList& list); + ~cFCOSpecListCanonicalIter(); + + void SeekBegin() const; + bool Done() const; + bool IsEmpty() const; + void Next() const; + //void Remove(); + // TODO --implement this the same as Remove() in the + // added iter. + const iFCOSpec* Spec() const; + iFCOSpec* Spec(); + const cFCOSpecAttr* Attr() const; + cFCOSpecAttr* Attr(); + +protected: + cFCOSpecList* mpSpecList; + + mutable std::list::iterator mIter; +}; + +inline cFCOSpecList::cFCOSpecList(const cFCOSpecList& rhs) +{ + *this = rhs; +} + +#endif //__FCOSPEC_H + diff --git a/src/fco/fcospeclist_t.cpp b/src/fco/fcospeclist_t.cpp new file mode 100644 index 0000000..0fcad8a --- /dev/null +++ b/src/fco/fcospeclist_t.cpp @@ -0,0 +1,166 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospeclist_t.cpp + +#include "stdfco.h" +#include "fcospeclist.h" +#include "core/debug.h" +#include "test/test.h" +#include "fcospecimpl.h" +#include "core/archive.h" +#include "core/serializerimpl.h" +#include "fcospecutil.h" +#include "fcospechelper.h" + +void TestFCOSpecList() +{ + cDebug d("TestFCOSpecList()"); + d.TraceDebug("Entering...\n"); + + cFCOSpecList specList; + + TEST(specList.IsEmpty()); + + cFCOSpecStopPointSet* pStopPts = new cFCOSpecStopPointSet; + iFCOSpec* pSpec = new cFCOSpecImpl(_T("s1"), NULL, pStopPts); + pSpec->SetStartPoint(cFCOName(_T("AAA"))); + pStopPts->Add(cFCOName(_T("AAA/SSS"))); + + specList.Add(pSpec); + pSpec->Release(); // the list now owns the spec. + + cFCOSpecStopPointSet* pStopPts2 = new cFCOSpecStopPointSet; + pSpec = new cFCOSpecImpl(_T("s2"), NULL, pStopPts2); + pSpec->SetStartPoint(cFCOName(_T("AAA"))); + pStopPts2->Add(cFCOName(_T("AAA/TTT"))); + + specList.Add(pSpec); + pSpec->Release(); // the list now owns the spec. + + pSpec = new cFCOSpecImpl(_T("s3"), NULL, new cFCOSpecStopPointSet); + pSpec->SetStartPoint(cFCOName(_T("AAA"))); + + specList.Add(pSpec); + + cFCOSpecImpl* pTestSpec = new cFCOSpecImpl(_T("test"), NULL, new cFCOSpecStopPointSet); + pTestSpec->SetStartPoint(cFCOName(_T("AAA"))); + + // Test Lookup() + iFCOSpec* pTmp; + TEST((pTmp = specList.Lookup(pSpec)) == pSpec); + pTmp->Release(); + TEST((pTmp = specList.Lookup(pTestSpec)) == pSpec); + pTmp->Release(); + + // Test iterator and Insert() order + cFCOSpecListCanonicalIter itr(specList); + TEST(itr.Spec()->GetName().compare(_T("s3")) == 0); + + pTestSpec->Release(); + pSpec->Release(); + + iFCOSpec* pPrev = NULL; + int i; + for (itr.SeekBegin(), i = 0; !itr.Done(); itr.Next(), ++i) + { + switch (i) + { + case 0: + pPrev = itr.Spec(); + break; + default: + TEST(iFCOSpecUtil::FCOSpecLessThan(*pPrev, *itr.Spec())); + pPrev = itr.Spec(); + break; + } + } + + cFCOSpecListAddedIter itra(specList); + TEST(itra.Spec()->GetName().compare(_T("s1")) == 0); + + for (itra.SeekBegin(), i = 0; !itra.Done(); itra.Next(), ++i) + { + switch (i) + { + case 0: + TEST(itra.Spec()->GetName().compare(_T("s1")) == 0); + break; + case 1: + TEST(itra.Spec()->GetName().compare(_T("s2")) == 0); + break; + case 2: + TEST(itra.Spec()->GetName().compare(_T("s3")) == 0); + break; + default: + TEST(false); + break; + } + } + + // test serialization + cMemoryArchive a; + cSerializerImpl s(a, cSerializerImpl::S_WRITE); + s.Init(); + specList.Write(&s); + s.Finit(); + a.Seek(0, cBidirArchive::BEGINNING); + + cFCOSpecList newSpecList; + cSerializerImpl s2(a, cSerializerImpl::S_READ); + s2.Init(); + newSpecList.Read(&s2); + s2.Finit(); + + // now to compare the two spec lists... + cFCOSpecListCanonicalIter itr1(specList), itr2(newSpecList); + for( itr1.SeekBegin(), itr2.SeekBegin(); ! itr1.Done(); itr1.Next(), itr2.Next() ) + { + TEST(iFCOSpecUtil::FCOSpecEqual(*itr1.Spec(), *itr2.Spec())); + } + + // test removal... + // I know this isn't the most thourough test in the world, but I am in a hurry! + d.TraceDebug("Testing removal...\n"); + cFCOSpecListAddedIter ai(specList); + ai.SeekBegin(); + while(! ai.Done()) + { + d.TraceDebug(_T("Removing spec %s\n"), ai.Spec()->GetName().c_str()); + ai.Remove(); + } + // better be empty! + TEST(specList.IsEmpty()); + + d.TraceDebug("TestFCOSpecList apparently worked fine!\n"); + return; +} + diff --git a/src/fco/fcospecutil.cpp b/src/fco/fcospecutil.cpp new file mode 100644 index 0000000..7aa4f73 --- /dev/null +++ b/src/fco/fcospecutil.cpp @@ -0,0 +1,58 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecutil.cpp +/////////////////////////////////////////////////////////////////////////////// +#include "stdfco.h" +#include "fcospecutil.h" +#include "fcospec.h" +#include "iterproxy.h" +#include "core/debug.h" +#include "fcospechelper.h" + +/////////////////////////////////////////////////////////////////////////////// +// class iFCOSpecUtil -- Utilities for iFCOSpec's +/////////////////////////////////////////////////////////////////////////////// + +bool iFCOSpecUtil::FCOSpecEqual(const iFCOSpec& lhs, const iFCOSpec& rhs) +{ + // TODO -- this doesn't take spec masks into account! + return (lhs.GetHelper()->Compare(rhs.GetHelper()) == iFCOSpecHelper::CMP_EQ); +} + +bool iFCOSpecUtil::FCOSpecLessThan(const iFCOSpec& lhs, const iFCOSpec& rhs) +{ + // TODO -- this doesn't take spec masks into account! + return (lhs.GetHelper()->Compare(rhs.GetHelper()) == iFCOSpecHelper::CMP_LT); +} + + diff --git a/src/fco/fcospecutil.h b/src/fco/fcospecutil.h new file mode 100644 index 0000000..32f0515 --- /dev/null +++ b/src/fco/fcospecutil.h @@ -0,0 +1,76 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcospecutil.h +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __FCOSPECUTIL_H +#define __FCOSPECUTIL_H + +#ifndef __FCOSPEC_H +#include "fcospec.h" +#endif + +class cFCOName; + +class iFCOSpecUtil +{ +public: + static bool FCOSpecEqual(const iFCOSpec& lhs, const iFCOSpec& rhs); + // Checks that the start point and all stop points are equal. + // Note: This may not make sense if the FCO spacs are of differing types, but in + // the name of simple implementation we define this as equality. + static bool FCOSpecLessThan(const iFCOSpec& lhs, const iFCOSpec& rhs); + // Defines an order of FCOSpecs. A FCOSpec is less than another if and only if + // the string concatination of start point and an ordered list of stop point + // are less than the other. + static bool SpecsOverlap(const iFCOSpec* pSpec1, const iFCOSpec* pSpec2); + // returns true if the specs "overlap", meaning there exists an fco which is contained + // in both specs. This is true if one specs's start point is contained in the other spec. +}; + +/////////////////////////////////////////////////////////////////////////////// +// inline implementation + +/////////////////////////////////////////////////////////////////////////////// +// SpecsOverlap -- returns true if one of the specs contains the other's +// start point +/////////////////////////////////////////////////////////////////////////////// +inline bool iFCOSpecUtil::SpecsOverlap(const iFCOSpec* pSpec1, const iFCOSpec* pSpec2) +{ + return (pSpec1->SpecContainsFCO(pSpec2->GetStartPoint()) || + pSpec2->SpecContainsFCO(pSpec1->GetStartPoint())); +} + + +#endif + diff --git a/src/fco/fcospecutil_t.cpp b/src/fco/fcospecutil_t.cpp new file mode 100644 index 0000000..ed0759c --- /dev/null +++ b/src/fco/fcospecutil_t.cpp @@ -0,0 +1,85 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospecutil_t.cpp + +#include "stdfco.h" +#include "fcospecutil.h" +#include "core/debug.h" +#include "test/test.h" +#include "fcospecimpl.h" +#include "iterproxy.h" +#include "fcospechelper.h" + +void TestFcoSpecUtil() +{ + cDebug d("TestFcoSpecUtil()"); + + // first check the equality operator... + cFCOSpecStopPointSet* pSet1 = new cFCOSpecStopPointSet; + cFCOSpecStopPointSet* pSet2 = new cFCOSpecStopPointSet; + cFCOSpecImpl* pSpec1 = new cFCOSpecImpl(_T("Spec1"), NULL, pSet1); + cFCOSpecImpl* pSpec2 = new cFCOSpecImpl(_T("Spec2"), NULL, pSet2); + + pSpec1->SetStartPoint(cFCOName(_T("Dog"))); + pSpec2->SetStartPoint(cFCOName(_T("Dog"))); + pSet1->Add(cFCOName(_T("Dog/Bark"))); + pSet2->Add(cFCOName(_T("Dog/Bark"))); + pSet1->Add(cFCOName(_T("Dog/Pant"))); + pSet2->Add(cFCOName(_T("Dog/Pant"))); + TEST(iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2)); + + // make them a little different... + cFCOSpecStopPointIter iter(*pSet1); + iter.SeekBegin(); + cFCOName removedName = iter.StopPoint(); + iter.Remove(); + pSet1->Add(cFCOName(_T("Dog/Scratch"))); + TEST(! iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2)); + + pSet1->Add(removedName); + TEST(! iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2)); + + + // TODO -- implement a more appropriate less-than test +/* pSpec1->SetStartPoint(cFCOName(_T("Dog"))); + pSpec2->AddStopPoint(cFCOName(_T("Howl"))); + TEST(! iFCOSpecUtil::FCOSpecEqual (*pSpec1, *pSpec2)); + TEST( iFCOSpecUtil::FCOSpecLessThan(*pSpec1, *pSpec2)); + pSpec1->AddStopPoint(cFCOName(_T("Howm"))); + TEST( iFCOSpecUtil::FCOSpecLessThan(*pSpec2, *pSpec1)); +*/ + + pSpec1->Release(); + pSpec2->Release(); + + d.TraceDebug("Leaving..\n"); +} diff --git a/src/fco/fcostrings.cpp b/src/fco/fcostrings.cpp new file mode 100644 index 0000000..369f528 --- /dev/null +++ b/src/fco/fcostrings.cpp @@ -0,0 +1,56 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fcostrings.cpp +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// +// + +#include "stdfco.h" +#include "fcostrings.h" + + +TSS_BeginStringtable( cFCO ) + + TSS_StringEntry( fco::STR_GENRE_FS, _T("FS") ), + TSS_StringEntry( fco::STR_GENRE_NTFS, _T("NTFS") ), + TSS_StringEntry( fco::STR_GENRE_NTREG, _T("NTReg") ), + TSS_StringEntry( fco::STR_GENRE_FS_V, _T("Unix File System") ), + TSS_StringEntry( fco::STR_GENRE_NTFS_V, _T("Windows NT File System") ), + TSS_StringEntry( fco::STR_GENRE_NTREG_V, _T("Windows NT Registry") ), + TSS_StringEntry( fco::STR_UNDEFINED, _T("n/a") ), + +TSS_EndStringtable( cFCO ) + + +// eof: fcostrings.cpp diff --git a/src/fco/fcostrings.h b/src/fco/fcostrings.h new file mode 100644 index 0000000..30683c0 --- /dev/null +++ b/src/fco/fcostrings.h @@ -0,0 +1,56 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fcostrings.h +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// + +#ifndef __FCOSTRINGS_H +#define __FCOSTRINGS_H + +#include "fco.h" + +TSS_BeginStringIds( fco ) + + STR_GENRE_FS, + STR_GENRE_NTFS, + STR_GENRE_NTREG, + STR_GENRE_FS_V, + STR_GENRE_NTFS_V, + STR_GENRE_NTREG_V, + STR_UNDEFINED + +TSS_EndStringIds( fco ) + +#endif //__FCOSTRINGS_H + diff --git a/src/fco/fcoundefprop.cpp b/src/fco/fcoundefprop.cpp new file mode 100644 index 0000000..8354f3b --- /dev/null +++ b/src/fco/fcoundefprop.cpp @@ -0,0 +1,141 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fcoundefprop.cpp +// Date....: 05/07/99 +// Creator.: +// +// The undefined FCO property +// + +#include "stdfco.h" +#include "fcoundefprop.h" +#include "core/errorutil.h" +#include "fcostrings.h" + +//============================================================================= +// cFCOUndefinedProp +// +// This class exists only as a singleton. iFCOPropSet derived classes will return a +// pointer to the singleton for properties that are undefined. +//============================================================================= + +IMPLEMENT_TYPEDSERIALIZABLE( + cFCOUndefinedProp, _T( "cFCOUndefinedProp" ), 0, 1 ); + +////////////////////////////////////////////////////////////////////////////// +// Singleton interface + +struct cFCOUndefinedPropProxy +{ + cFCOUndefinedProp mUndef; +}; + + +cFCOUndefinedProp* cFCOUndefinedProp::GetInstance() +{ + static cFCOUndefinedPropProxy _default; + return &_default.mUndef; +} + + +////////////////////////////////////////////////////////////////////////////// +// Method definition + +cFCOUndefinedProp::cFCOUndefinedProp() +{ +} + +cFCOUndefinedProp::~cFCOUndefinedProp() +{ +} + +TSTRING cFCOUndefinedProp::AsString() const +{ + return TSS_GetString( cFCO, fco::STR_UNDEFINED ); +} + +iFCOProp::CmpResult +cFCOUndefinedProp::Compare( const iFCOProp* rhs, iFCOProp::Op op ) const +{ + if ( op == iFCOProp::OP_GT || + op == iFCOProp::OP_LT || + op == iFCOProp::OP_GE || + op == iFCOProp::OP_LE ) + { + // It is not very well-defined what we should do if you are testing inequality + // on an undefined property. In 2.1 we never compare inequality so this should + // not happen. This changes some code will need to be re-written. + ASSERTMSG( + false, + "cFCOUndefinedProp does not support >, <, >=, or <= compares!" ); + + return iFCOProp::CMP_UNSUPPORTED; + } + + ASSERT( op == iFCOProp::OP_EQ || op == iFCOProp::OP_NE ); + + + if ( rhs->GetType() != GetType() ) + { + // undefined prop is unequal to all other props + return + ( op == iFCOProp::OP_EQ ) + ? iFCOProp::CMP_FALSE + : iFCOProp::CMP_TRUE; + } + else if ( op == iFCOProp::OP_EQ ) + { + return iFCOProp::CMP_TRUE; + } + else + { + return iFCOProp::CMP_FALSE; + } +} + +void cFCOUndefinedProp::Read(iSerializer* pSerializer, int32 version) +{ + ThrowAndAssert( INTERNAL_ERROR("fcoundefprop.cpp") ); +} + +void cFCOUndefinedProp::Write(iSerializer* pSerializer) const +{ + ThrowAndAssert( INTERNAL_ERROR("fcoundefprop.cpp") ); +} + +void cFCOUndefinedProp::Copy(const iFCOProp* rhs) +{ + ThrowAndAssert( INTERNAL_ERROR("fcoundefprop.cpp") ); +} + +// eof: fcoundefprop.cpp diff --git a/src/fco/fcoundefprop.h b/src/fco/fcoundefprop.h new file mode 100644 index 0000000..a269c81 --- /dev/null +++ b/src/fco/fcoundefprop.h @@ -0,0 +1,79 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoundefprop.h -- the undefined FCO property +// +#ifndef __FCOUNDEFPROP_H +#define __FCOUNDEFPROP_H + +#ifndef __FCOPROP_H +#include "fcoprop.h" +#endif + +//============================================================================= +// cFCOUndefinedProp +// +// This class exists only as a singleton. iFCOPropSet derived classes will return a +// pointer to the singleton for properties that are undefined. +//============================================================================= + +class cFCOUndefinedProp : public iFCOProp +{ +public: + DECLARE_TYPEDSERIALIZABLE() // type information + + static cFCOUndefinedProp* GetInstance(); + // access to the singleton + + // from iFCOProp + virtual TSTRING AsString() const; + virtual CmpResult Compare(const iFCOProp* rhs, Op op) const; + virtual void Copy(const iFCOProp* rhs); + +private: + + friend struct cFCOUndefinedPropProxy; + + cFCOUndefinedProp(); + virtual ~cFCOUndefinedProp(); + // don't new or construct these on the stack + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eInternal) + virtual void Write(iSerializer* pSerializer) const; // throw (eInternal) + // These functions should never be called, and they will throw and eInternal if they are. +}; + + + +#endif // __FCOUNDEFPROP_H + diff --git a/src/fco/fcovisitor.h b/src/fco/fcovisitor.h new file mode 100644 index 0000000..04b0861 --- /dev/null +++ b/src/fco/fcovisitor.h @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcovisitor.h +// +// iFCOVisitor -- top-level visitor interface. Right now, this only contains +// GetGenre(), which returns the visitor's type +#ifndef __FCOVISITOR_H +#define __FCOVISITOR_H + +#ifndef __TYPED_H +#include "core/typed.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// IMPORTANT! -- Note that although the concept of "genre" is the same as in the +// design document, a genre seems to be fundamentally equivalent to a cType +// as defined in typed.h. Therefore, the elements in the visitor pattern will +// do their safe cast based on the visitor's iTyped interface. +/////////////////////////////////////////////////////////////////////////////// +class iFCOVisitor : public iTyped +{ +public: + // it is sad to note that without genres, iFCOVisitor now has _nothing_! ... + // never a good sign -mdb +protected: + virtual ~iFCOVisitor() {}; +}; + +#endif + diff --git a/src/fco/fsspec_t.cpp b/src/fco/fsspec_t.cpp new file mode 100644 index 0000000..a24ca42 --- /dev/null +++ b/src/fco/fsspec_t.cpp @@ -0,0 +1,111 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcospecimpl test driver + +#include "stdfco.h" +#include "fcospecimpl.h" +#include "core/debug.h" +//#include "fs/fsdatasource.h" +#include "iterproxy.h" +#include "core/error.h" +#include "test/test.h" +#include "fcospechelper.h" +#include "core/fsservices.h" + +/////////////////////////////////////////////////////////////////////////////// +// PrintFCOTree -- recursively prints an fco's name and all of it's children's +/////////////////////////////////////////////////////////////////////////////// +/* +static void PrintFCOTree(const iFCO* pFCO, cDebug d, int depth) +{ + TSTRING prefix; + for(int i=0; iGetName().AsString().c_str()); + + const cIterProxy pi = pFCO->GetChildSet()->GetIter(); + + for(pi->SeekBegin(); ! pi->Done(); pi->Next()) + { + PrintFCOTree(pi->FCO(), d, depth+1); + } +} +*/ + +void TestFCOSpecImpl() +{ + cDebug d("TestFCOSpecImpl"); + d.TraceDebug("Entering...\n"); + + //********************* + // + // TODO -- As of tripwire 2.1, this needs to be updated! + // 28 Jan 99 mdb + // + //********************* + ASSERT( false ); +/* + cFSDataSource dataSrc; + iFSServices* pFSS = iFSServices::GetInstance(); + + + // test AllChildStopPoint fcos... + d.TraceDebug("Now testing a spec whose start point is the only thing it maps to (%s)\n", TEMP_DIR); + cFCOSpecImpl* pSpec2 = new cFCOSpecImpl(TEMP_DIR, &dataSrc, new cFCOSpecNoChildren); + pSpec2->SetStartPoint(cFCOName(TEMP_DIR)); + iFCO* pFCO = pSpec2->CreateFCO(pSpec2->GetStartPoint(), iFCODataSource::CHILDREN_ALL); + PrintFCOTree(pFCO, d, 0); + pFCO->Release(); + + // create an FSSpec and set up some start and stop points... + cFCOSpecStopPointSet* pSet = new cFCOSpecStopPointSet; + cFCOSpecImpl* pSpec = new cFCOSpecImpl(_T("Test FSSpec"), &dataSrc, pSet); + pSpec->SetStartPoint(cFCOName(_T("d:/code"))); + pSet->Add(cFCOName(_T("d:/code/open gl"))); + pSet->Add(cFCOName(_T("d:/code/pclient"))); + + // create all the fcos... + pFCO = pSpec->CreateFCO(pSpec->GetStartPoint(), iFCODataSource::CHILDREN_ALL); + ASSERT(pFCO); + PrintFCOTree(pFCO, d, 0); + pFCO->Release(); + + // TODO -- test Clone(), copy ctor, operator= + + pSpec->Release(); + return; +*/ +} + diff --git a/src/fco/genre_t.cpp b/src/fco/genre_t.cpp new file mode 100644 index 0000000..d1f95bb --- /dev/null +++ b/src/fco/genre_t.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genre_t.cpp +// + +#include "stdfco.h" +#include "genreswitcher.h" +#include "test/test.h" + +#ifdef _CPPRTTI +#include "fs/fsfactory.h" +#include "ntfs/ntfsfactory.h" +#endif + +void TestGenreSwitcher() +{ +#pragma message( __FILE__ "(1) : TODO - implement this test file") +#if 0 + cDebug d("TestGenreSwitcher"); + d.TraceDebug("Entering...\n"); + + // normally we use the cGenreSwitcher::GetInstance() interface + // to get access the class singleton. But for testing purposes + // we will put have one reside on the stack. + cGenreSwitcher genreSwitcher; + + TEST(genreSwitcher.CurrentGenre() == cGenre::GENRE_INVALID); + + genreSwitcher.SelectGenre(cGenre::FS); + TEST(genreSwitcher.CurrentGenre() == cGenre::FS); + #ifdef _CPPRTTI + TEST(typeid(*iTWFactory::GetInstance()) == typeid(cFSFactory)); + #endif + + genreSwitcher.SelectGenre(cGenre::NTFS); + TEST(genreSwitcher.CurrentGenre() == cGenre::NTFS); + #ifdef _CPPRTTI + TEST(typeid(*iTWFactory::GetInstance()) == typeid(cNTFSFactory)); + #endif + + d.TraceDebug("All tests passed.\n"); +#endif //#if 0 +} diff --git a/src/fco/genreinfo.cpp b/src/fco/genreinfo.cpp new file mode 100644 index 0000000..10594d5 --- /dev/null +++ b/src/fco/genreinfo.cpp @@ -0,0 +1,68 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: genreinfo.h +// Date....: 05/17/99 +// Creator.: bmcfeely +// +// + +#include "stdfco.h" +#include "genreinfo.h" + +// after registering, cGenreInfo will own the iTWFactory* +cGenreInfo::cGenreInfo( cGenre::Genre id, const TSTRING& sSN, const TSTRING& sLN, iTWFactory* pF ) + : m_ID( id ), + m_sShortName( sSN ), + m_sLongName( sLN ), + m_pFactory( pF ) +{ + ASSERT( IsValid() ); +} + +cGenreInfo::~cGenreInfo() +{ +} + +bool cGenreInfo::IsValid() const +{ + return( + ( m_ID != cGenre::GENRE_INVALID ) + && + ( m_pFactory != NULL ) + && + ( ! m_sShortName.empty() ) + && + ( ! m_sLongName.empty() ) + ); +} + diff --git a/src/fco/genreinfo.h b/src/fco/genreinfo.h new file mode 100644 index 0000000..a2024e7 --- /dev/null +++ b/src/fco/genreinfo.h @@ -0,0 +1,83 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreinfo.h +// + +#ifndef __GENREINFO_H +#define __GENREINFO_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __FCOGENRE_H +#include "fcogenre.h" +#endif + +#ifndef __TWFACTORY_H +#include "twfactory.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +// +// GenreInfo -- contains all info about genres except +// for whether or not it is the default genre for the system +// +class cGenreInfo +{ +public: + cGenreInfo( cGenre::Genre id, const TSTRING& sSN, const TSTRING& sLN, iTWFactory* pF ); + // after registering, cGenreInfo will own the iTWFactory* + virtual ~cGenreInfo(); + + bool IsValid() const; + // makes sure all fields have valid values + + // + // data members + // + cGenre::Genre m_ID; + TSTRING m_sShortName; + TSTRING m_sLongName; + iTWFactory* m_pFactory; +}; + +#endif //__GENREINFO_H + diff --git a/src/fco/genrespeclist.cpp b/src/fco/genrespeclist.cpp new file mode 100644 index 0000000..82a36ee --- /dev/null +++ b/src/fco/genrespeclist.cpp @@ -0,0 +1,102 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genrespeclist.cpp +// + +#include "stdfco.h" +#include "genrespeclist.h" + +//============================================================================= +// class cGenreSpecListPair +//============================================================================= + +cGenreSpecListPair::cGenreSpecListPair() +{ + mGenre = cGenre::GENRE_INVALID; +} + +cGenreSpecListPair::~cGenreSpecListPair() +{ +} + +cGenreSpecListPair& cGenreSpecListPair::operator = (const cGenreSpecListPair& rhs) +{ + mGenre = rhs.mGenre; + mSpecList = rhs.mSpecList; + return *this; +} + +cGenre::Genre cGenreSpecListPair::GetGenre() const +{ + return mGenre; +} + +cFCOSpecList& cGenreSpecListPair::GetSpecList() +{ + return mSpecList; +} + +void cGenreSpecListPair::SetGenre(cGenre::Genre genre) +{ + mGenre = genre; +} + +void cGenreSpecListPair::SetSpecList(const cFCOSpecList& speclist) +{ + mSpecList = speclist; +} + +//============================================================================= +// class cGenreSpecListVector +//============================================================================= + +cGenreSpecListVector::cGenreSpecListVector() +{ +} + +cGenreSpecListVector::cGenreSpecListVector(const cGenreSpecListVector& rhs) +{ + *this = rhs; +} + +cGenreSpecListVector::~cGenreSpecListVector() +{ +} + +cGenreSpecListVector& cGenreSpecListVector::operator = (const cGenreSpecListVector& rhs) +{ + ((std::vector*)this)->operator = (rhs); + return *this; +} + + diff --git a/src/fco/genrespeclist.h b/src/fco/genrespeclist.h new file mode 100644 index 0000000..da1e646 --- /dev/null +++ b/src/fco/genrespeclist.h @@ -0,0 +1,97 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genrespeclist.h +// +// class cGenreSpecListPair +// class cGenreSpecListVector + +#ifndef __GENRESPECLIST_H +#define __GENRESPECLIST_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __FCOGENRE_H +#include "fcogenre.h" +#endif + +#ifndef __FCOSPECLIST_H +#include "fcospeclist.h" +#endif + +//============================================================================= +// class cGenreSpecListPair +//============================================================================= + +class cGenreSpecListPair +{ +public: + cGenreSpecListPair(); + cGenreSpecListPair(const cGenreSpecListPair& rhs); + ~cGenreSpecListPair(); + + cGenreSpecListPair& operator = (const cGenreSpecListPair& rhs); + + cGenre::Genre GetGenre() const; + cFCOSpecList& GetSpecList(); + + void SetGenre(cGenre::Genre genre); + void SetSpecList(const cFCOSpecList& speclist); + +private: + cGenre::Genre mGenre; + cFCOSpecList mSpecList; +}; + +inline cGenreSpecListPair::cGenreSpecListPair(const cGenreSpecListPair& rhs) +{ + *this = rhs; +} + +//============================================================================= +// class cGenreSpecListVector +//============================================================================= + +class cGenreSpecListVector : public std::vector +{ +public: + cGenreSpecListVector(); + cGenreSpecListVector(const cGenreSpecListVector& rhs); + ~cGenreSpecListVector(); + + cGenreSpecListVector& operator = (const cGenreSpecListVector& rhs); +}; + +#endif + diff --git a/src/fco/genrespeclist_t.cpp b/src/fco/genrespeclist_t.cpp new file mode 100644 index 0000000..bf91455 --- /dev/null +++ b/src/fco/genrespeclist_t.cpp @@ -0,0 +1,96 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genrespeclist_t.cpp +// + +#include "stdfco.h" +#include "genrespeclist.h" +#include "test/test.h" +#include "fcospecimpl.h" + +void TestGenreSpecList() +{ +#pragma message( __FILE__ "(1) : TODO - implement this test file") +#if 0 + + cDebug d("TestGenreSpecList"); + d.TraceDebug("Entering...\n"); + + // cGenreSpecListPair + cGenreSpecListPair gslPair; + + TEST(gslPair.GetGenre() == cGenre::GENRE_INVALID); + + gslPair.SetGenre(cGenre::FS); + TEST(gslPair.GetGenre() == cGenre::FS); + + cFCOSpecList speclist; + cFCOSpecImpl* fsSpec = new cFCOSpecImpl(_T("test fsspce name"), NULL); + + speclist.Add(fsSpec); + fsSpec->Release(); + + gslPair.SetSpecList(speclist); + TEST(gslPair.GetSpecList().Lookup(fsSpec)->GetName() == fsSpec->GetName()); + + cGenreSpecListPair gslPair2(gslPair); + TEST(gslPair.GetGenre() == gslPair2.GetGenre()); + TEST(gslPair.GetSpecList().Lookup(fsSpec)->GetName() == gslPair2.GetSpecList().Lookup(fsSpec)->GetName()); + + cGenreSpecListPair gslPair3; + gslPair3 = gslPair; + TEST(gslPair.GetGenre() == gslPair3.GetGenre()); + TEST(gslPair.GetSpecList().Lookup(fsSpec)->GetName() == gslPair3.GetSpecList().Lookup(fsSpec)->GetName()); + + // cGenreSpecListVector + cGenreSpecListVector gslVector; + gslVector.push_back(gslPair); + gslVector.push_back(gslPair2); + gslVector.push_back(gslPair3); + + TEST(gslVector.at(0).GetGenre() == gslPair.GetGenre()); + TEST(gslVector.at(0).GetSpecList().Lookup(fsSpec) != 0); + TEST(gslVector.at(0).GetSpecList().Lookup(fsSpec)->GetName() == gslPair.GetSpecList().Lookup(fsSpec)->GetName()); + + TEST(gslVector.at(1).GetGenre() == gslPair2.GetGenre()); + TEST(gslVector.at(1).GetSpecList().Lookup(fsSpec) != 0); + TEST(gslVector.at(1).GetSpecList().Lookup(fsSpec)->GetName() == gslPair2.GetSpecList().Lookup(fsSpec)->GetName()); + + TEST(gslVector.at(2).GetGenre() == gslPair3.GetGenre()); + TEST(gslVector.at(2).GetSpecList().Lookup(fsSpec) != 0); + TEST(gslVector.at(2).GetSpecList().Lookup(fsSpec)->GetName() == gslPair3.GetSpecList().Lookup(fsSpec)->GetName()); + + d.TraceDebug("All tests passed.\n"); +#endif +} + diff --git a/src/fco/genreswitcher.cpp b/src/fco/genreswitcher.cpp new file mode 100644 index 0000000..6e310cd --- /dev/null +++ b/src/fco/genreswitcher.cpp @@ -0,0 +1,265 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreswitcher.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfco.h" +#include "genreswitcher.h" +#include "core/errorgeneral.h" +#include "genreinfo.h" +#include "core/errorutil.h" + +//========================================================================= +// STATIC MEMBERS +//========================================================================= + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + +// use to get global instance of this class +/* static */ cGenreSwitcher* cGenreSwitcher::GetInstance() +{ + static cGenreSwitcher s_Instance; + return &s_Instance; +} + +cGenreSwitcher::cGenreSwitcher() + : m_pDefaultGenre( NULL ), + m_curGenre( cGenre::GENRE_INVALID ) +{ +} + +cGenreSwitcher::~cGenreSwitcher() +{ +} + +// set the current genre +// thows an eError if newGenre is invalid +void cGenreSwitcher::SelectGenre( cGenre::Genre g ) +{ + iTWFactory::SetFactory( GetFactoryForGenre( g ) ); + m_curGenre = g; +} + +cGenre::Genre cGenreSwitcher::CurrentGenre() +{ + return m_curGenre; +} + +cGenre::Genre cGenreSwitcher::GetDefaultGenre() +{ + cGenre::Genre defGenre = cGenre::GENRE_INVALID; + + if( m_pDefaultGenre != NULL ) + defGenre = m_pDefaultGenre->m_ID; + + ASSERT( defGenre != cGenre::GENRE_INVALID ); + return defGenre; +} + +void cGenreSwitcher::RegisterGenre( const cGenreInfo* pGI, RegisterFlags flags /* = REGISTER_FLAGS_NONE */ ) +{ + cDebug d("cGenreSwitcher::RegisterGenre"); + d.TraceDebug( _T("ID: %x, long name: %s, short name: %s\n"), pGI->m_ID, pGI->m_sLongName.c_str(), pGI->m_sShortName.c_str() ); + + // + // validate params + // + ASSERT( NULL != pGI ); + ASSERT( pGI->IsValid() ); + + // + // can only be one of each genre ID + // + if( m_vGenres.find( pGI ) != m_vGenres.end() ) + { + // TODO: correct behavior? Should this be allowable/ignored? + THROW_INTERNAL( "genreswitcher.cpp" ); // Attempt to register duplicate genre ID. + } + + // + // save genre info + // + m_vGenres.push_back( pGI ); + + // + // set default genre if appropriate + // + if( flags & REGISTER_FLAGS_DEFAULT ) + { + // can only be one default genre + // TODO: should we allow more than one lib to vie for default genre on a platform? + if( NULL != m_pDefaultGenre ) + THROW_INTERNAL( "genreswitcher.cpp" ); // "Two genres claim default genre status." ); + + // save as default genre + m_pDefaultGenre = pGI; + } +} + + +bool cGenreSwitcher::IsGenreRegistered( cGenre::Genre g ) +{ + return( m_vGenres.find( g ) != m_vGenres.end() ); +} + + +bool cGenreSwitcher::IsGenreAppropriate( cGenre::Genre g ) +{ +#if IS_UNIX + const uint32 platformMask = cGenre::PLATFORM_MASK_UNIX; + #else + #error who am I? + #endif + + return( ( platformMask & g ) != 0 ); +} + + +iTWFactory* cGenreSwitcher::GetFactoryForGenre( cGenre::Genre g ) +{ + cGenreInfoVec::const_iterator i = m_vGenres.find( g ); + + if( i == m_vGenres.end() ) + { + ThrowAndAssert( INTERNAL_ERROR( "Switch to invalid genre factory") ); + } + + ASSERT( (*i)->m_pFactory != NULL ); + return( (*i)->m_pFactory ); +} + + +// Convert an enum to a string. Verbose flag specifies +// whether to return "NTReg" or "NT Registry". +const TCHAR* cGenreSwitcher::GenreToString( cGenre::Genre g, bool verbose) +{ + cGenreInfoVec::const_iterator i = m_vGenres.find( g ); + if( i != m_vGenres.end() ) + { + ASSERT( (*i)->m_ID != cGenre::GENRE_INVALID ); + return( verbose ? (*i)->m_sLongName.c_str() : (*i)->m_sShortName.c_str() ); + } + + // didn't recognize genre ID + ASSERT( false ); + return( NULL ); +} + +// Narrow and wide character conversions. These functions will be +// able to intelligently handle case sesitivity and verbose or narrow +// versions of the string. +// GENRE_INVALID will be returned on error. + + +cGenre::Genre cGenreSwitcher::StringToGenre( const TCHAR* sz ) +{ + // must convert to TSTRING + TSTRING sGenre( sz ); + + cGenreInfoVec::const_iterator i = m_vGenres.find( sGenre ); + if( i != m_vGenres.end() ) + { + return( (*i)->m_ID ); + } + + return( cGenre::GENRE_INVALID ); +} + +/* TODO: This is old code - dmb +cGenre::Genre cGenreSwitcher::StringToGenre( const wchar_t* wsz ) +{ + // must convert to TSTRING + TSTRING sGenre = cStringUtil::WstrToTstr( wsz ); + + cGenreInfoVec::const_iterator i = _vGenres.find( sGenre ); + if( i != _vGenres.end() ) + { + return( (*i)->_ID ); + } + + return( cGenre::GENRE_INVALID ); +} +*/ + +//========================================================================= +// PRIVATE METHOD CODE +//========================================================================= + +// returns true if there is a cGenreInfo stored in _vGenres that has an ID which +// matches this pGI's ID +cGenreInfoVec::const_iterator cGenreInfoVec::find( cGenre::Genre g ) const +{ + const_iterator i; + for( i = begin(); i != end(); i++ ) + { + ASSERT( (*i)->m_ID != cGenre::GENRE_INVALID ); + + if( g == (*i)->m_ID ) + return i; + } + + return i; +} + +cGenreInfoVec::const_iterator cGenreInfoVec::find( const cGenreInfo* pGI ) const +{ + ASSERT( NULL != pGI ); + return( find( pGI->m_ID ) ); +} + +// sGenre can be either short or long name +cGenreInfoVec::const_iterator cGenreInfoVec::find( const TSTRING& sGenre ) const +{ + const_iterator i; + for( i = begin(); i != end(); i++ ) + { + ASSERT( (*i)->m_ID != cGenre::GENRE_INVALID ); + + // + // compare against long and short name + // + if (_tcsicmp(sGenre.c_str(), (*i)->m_sLongName.c_str()) == 0 || + _tcsicmp(sGenre.c_str(), (*i)->m_sShortName.c_str()) == 0) + break; + } + + return( i ); +} + + diff --git a/src/fco/genreswitcher.h b/src/fco/genreswitcher.h new file mode 100644 index 0000000..c1d2ea9 --- /dev/null +++ b/src/fco/genreswitcher.h @@ -0,0 +1,161 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreswitcher.h +// + +#ifndef __GENRESWITCHER_H +#define __GENRESWITCHER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "fcogenre.h" +#include "genreinfo.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + + +//------------------------------------------------- +// +// class cGenreInfoVec -- +// +//------------------------------------------------- + +class cGenreInfoVec : public std::vector< const cGenreInfo* > +{ +public: + //------------------------------------------------------------- + // Util Functions + //------------------------------------------------------------- + const_iterator find( const cGenreInfo* pGI ) const; + // returns true if there is a cGenreInfo stored in m_vGenres that has an ID which + // matches this pGI's ID + const_iterator find( cGenre::Genre g ) const; + // finds by genre ID + const_iterator find( const TSTRING& sGenre ) const; + // finds both long and short names +}; + +//------------------------------------------------- +// +// class cGenreSwitcher -- +// +//------------------------------------------------- + +// classes that register to the cGenreSwitcher are responsible for setting +// a default value. +// access through GetInstance() +class cGenreSwitcher +{ +public: + + //------------------------------------------------------------- + // Singleton Manipulation + //------------------------------------------------------------- + static cGenreSwitcher* GetInstance(); + + //------------------------------------------------------------- + // Genre Selection + //------------------------------------------------------------- + void SelectGenre(cGenre::Genre newGenre); + // set the current genre + // thows an eError if newGenre is invalid + + cGenre::Genre CurrentGenre(); + // returs the current genre, or cGenre::GENRE_INVALID if no genre + // has be selected since construction + + iTWFactory* GetFactoryForGenre( cGenre::Genre ); + // returns the tw factory appropriate for the given genre + // throws eError if genre is invalid. + + cGenre::Genre GetDefaultGenre(); + // returns ID of default registered genre + + //------------------------------------------------------------- + // Genre Checking + //------------------------------------------------------------- + bool IsGenreAppropriate( cGenre::Genre g ); + // is this genre supposed to be used with this platform? + bool IsGenreRegistered( cGenre::Genre g ); + // is this genre recognized? + + //------------------------------------------------------------- + // Genre Name/ID Conversion + //------------------------------------------------------------- + const TCHAR* GenreToString( cGenre::Genre genre, bool verbose = false ); + // Convert an enum to a string. Verbose flag specifies + // whether to return "NTReg" or "NT Registry". + // NULL will be returned on error. + + cGenre::Genre StringToGenre( const TCHAR* sz ); + // TODO: remove this - dmb cGenre::Genre StringToGenre( const wchar_t* wsz ); + // Narrow and wide character conversions. These functions will be + // able to intelligently handle case sesitivity and verbose or narrow + // versions of the string. + // GENRE_INVALID will be returned on error. + + //------------------------------------------------------------- + // Genre Registration + //------------------------------------------------------------- + enum RegisterFlags { REGISTER_FLAGS_NONE = 0x00, REGISTER_FLAGS_DEFAULT = 0x01 }; + void RegisterGenre( const cGenreInfo* pGI, RegisterFlags flags = REGISTER_FLAGS_NONE ); + // cGenreSwitcher does not own the cGenreInfo + + ~cGenreSwitcher(); +private: + + //------------------------------------------------------------- + // Ctor and Dtor -- only access to cGenreSwitcher is through GetInstance() + //------------------------------------------------------------- + cGenreSwitcher(); + + //------------------------------------------------------------- + // Private Data Members + //------------------------------------------------------------- + const cGenreInfo* m_pDefaultGenre; // points to the default registered genre + cGenreInfoVec m_vGenres; // stores all registered genre information + cGenre::Genre m_curGenre; // points to the current genre +}; + +#endif //__GENRESWITCHER_H + diff --git a/src/fco/genreswitcher_t.cpp b/src/fco/genreswitcher_t.cpp new file mode 100644 index 0000000..431271b --- /dev/null +++ b/src/fco/genreswitcher_t.cpp @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreswitcher_t.h +// + +#include "stdfco.h" +#include "genreswitcher.h" +#include "test/test.h" + +void TestGenre() +{ + cDebug d("TestGenre"); + d.TraceDebug("Entering...\n"); + + TEST(cGenreSwitcher::GetInstance()->StringToGenre(cGenreSwitcher::GetInstance()->GenreToString(0x00020001)) == 0x00020001); + TEST(cGenreSwitcher::GetInstance()->StringToGenre(cGenreSwitcher::GetInstance()->GenreToString(0x00010001)) == 0x00010001); + TEST(cGenreSwitcher::GetInstance()->StringToGenre(cGenreSwitcher::GetInstance()->GenreToString(0x00010002)) == 0x00010002); + + TEST(cGenreSwitcher::GetInstance()->StringToGenre(_T("fs")) == 0x00020001); + TEST(cGenreSwitcher::GetInstance()->StringToGenre(_T("NT file system")) == 0x00010001); + TEST(cGenreSwitcher::GetInstance()->StringToGenre(_T("none of the above")) == cGenre::GENRE_INVALID); + + d.TraceDebug("All tests passed.\n"); +} diff --git a/src/fco/iterproxy.h b/src/fco/iterproxy.h new file mode 100644 index 0000000..aa50bdb --- /dev/null +++ b/src/fco/iterproxy.h @@ -0,0 +1,68 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// iterproxy.h +// +// cIterProxy<> -- smart pointer for iterator classes used in tripwire. the +// iterator must support being destroyed with a member function called +// ReleaseIter() +#ifndef __ITERPROXY_H +#define __ITERPROXY_H + +//////////////////////////////////////////////////// +// cIterProxy -- a smart pointer class +// for fco iterators. It can be dereferenced +// and assigned to like a pointer, but it calls +// mpIter->Release() when it is destroyed, unless +// mpIter == NULL. +//////////////////////////////////////////////////// + +template +class cIterProxy +{ +public: + cIterProxy(TYPE* pIter = NULL) : mpIter(pIter) {}; + cIterProxy(const TYPE* pIter) : mpIter((TYPE*)pIter) {}; + ~cIterProxy() { if (mpIter) mpIter->DestroyIter(); } + operator TYPE*() { return mpIter; } + operator const TYPE*() const { return mpIter; } + TYPE* operator->() { return mpIter; } + const TYPE* operator->() const { return mpIter; } + TYPE* operator=(TYPE* rhs) { mpIter = rhs; return mpIter; } +private: + TYPE* mpIter; +}; + + + +#endif + diff --git a/src/fco/parsergenreutil.h b/src/fco/parsergenreutil.h new file mode 100644 index 0000000..2b23edc --- /dev/null +++ b/src/fco/parsergenreutil.h @@ -0,0 +1,74 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////// +// parsergenreutil.h +// +// iParserGenreUtil holds parser utility functions for which genre-specific +// information is needed. +// + +#ifndef __PARSERGENREUTIL_H +#define __PARSERGENREUTIL_H + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class cFCOPropVector; +class cFCOName; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +class iParserGenreUtil +{ +public: + virtual bool MapStringToProperty( const TSTRING& str, int& propIndex ) const = 0; + // maps the given string to an index into a property vector for the genre + virtual void AddSubTypeProps( cFCOPropVector& v ) const = 0; + // adds all properties that define object sub-type in genre (e.g. PROP_FILETYPE in FS) + virtual void InterpretFCOName( const std::list& l, cFCOName& nameOut ) const = 0; // throw( eParserGenreUtil ) + // given the input string list from the policy file, creates the cFCOName + virtual bool EnumPredefinedVariables( int index, TSTRING&, TSTRING& ) const = 0; + // set index to 0 before first call, then increment for each subsequent call. + // returns true if more var/val pairs + virtual bool IsAbsolutePath( const TSTRING& strPath ) const = 0; + // returns true if the path is an absolute path, and false if it's relative. + virtual bool HasSingleLetterProps() const = 0; + // returns true if this genre uses single-letter to represent object properties + // in the policy language and the command line. If it returns false, the genre + // uses &-separated words. +}; + +#endif //__PARSERGENREUTIL_H + diff --git a/src/fco/propset.h b/src/fco/propset.h new file mode 100644 index 0000000..be6ef67 --- /dev/null +++ b/src/fco/propset.h @@ -0,0 +1,69 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// propset.h -- Marcro definitions common to all property sets +// +// These macros were moved to a common file to provide a central place for +// their definitions. +// + +#ifndef __PROPSET_H +#define __PROPSET_H + +/////////////////////////////////////////////////////////////////////////////// +// Convience macros for defining properties. +// +// PROPERTY() is used for properties whose values can be set by a passed in argument +// PROPERTY_OBJ() is used other properties whose value must be set using the object +// +// These macro's are different because it does not make sense to set a +// signature value (at least in the MD5 case where it takes a 128 bit number!). +/////////////////////////////////////////////////////////////////////////////// +#define PROPERTY(TYPE, NAME, INDEX)\ +private:\ + TYPE m##NAME;\ +public:\ +void Set##NAME (TYPE::ValueType value) { mValidProps.AddItem(INDEX); m##NAME.SetValue(value); }\ +TYPE::ValueType Get##NAME () const { ASSERT(mValidProps.ContainsItem(INDEX)); return m##NAME.GetValue(); }\ +void SetUndefined##NAME () { mValidProps.AddItem(INDEX); mUndefinedProps.AddItem(INDEX); } + +#define PROPERTY_OBJ(TYPE, NAME, INDEX)\ +private:\ + TYPE m##NAME;\ +public:\ +TYPE* Get##NAME () { return &m##NAME; }\ +void SetValid##NAME (bool valid) { if (valid) mValidProps.AddItem(INDEX); else mValidProps.RemoveItem(INDEX); }\ +void SetDefined##NAME (bool defined) { SetValid##NAME(true); if (!defined) mUndefinedProps.AddItem(INDEX); else mUndefinedProps.RemoveItem(INDEX); } +/////////////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/src/fco/signature.cpp b/src/fco/signature.cpp new file mode 100644 index 0000000..b2ad5c6 --- /dev/null +++ b/src/fco/signature.cpp @@ -0,0 +1,818 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// signature.cpp -- interface for calculating file signatures +/////////////////////////////////////////////////////////////////////////////// + +#include "stdfco.h" +#include "signature.h" +#include "core/errorgeneral.h" +#include "core/serializer.h" +#include +#include +#include "fcoundefprop.h" +#include "core/archive.h" +#ifndef HAVE_OPENSSL_MD5_H +# ifdef HAVE_STRINGS_H +# include /* for bcopy(), this is only needed for Solaris */ +# endif +#endif + +using namespace std; + +// Vector for base64 conversion +// +// The standard "digits" for base64 are "[A-Z][a-z][0-9]+/" +// (see RFC 2045 at http://sunsite.doc.ic.ac.uk/rfc/rfc2045.txt). +// However, Tripwire 1.3 used a different set of characters. +// +// In order to more closely follow the standard I changed our +// encoding to the standard. dmb 09-30-1998 +// +static char base64vec[] = + //"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:."; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/////////////////////////////////////////////////////////////////////////////// +// class iSignature -- Interface all signatures will implement. +/////////////////////////////////////////////////////////////////////////////// + +iFCOProp::CmpResult iSignature::Compare(const iFCOProp* rhs, Op op) const +{ + // make sure we support this operation + if(op != iFCOProp::OP_EQ && + op != iFCOProp::OP_NE) + { + ASSERT(false); + return iFCOProp::CMP_UNSUPPORTED; + } + + // compares with undefined props are not equal + if (rhs->GetType() == cFCOUndefinedProp::GetInstance()->GetType()) + { + return (op == iFCOProp::OP_EQ) ? iFCOProp::CMP_FALSE : iFCOProp::CMP_TRUE; + } + + // make sure we are the right type... + if(this->GetType() != rhs->GetType()) + { + ASSERT(false); + return iFCOProp::CMP_WRONG_PROP_TYPE; + } + + ASSERT((op == iFCOProp::OP_EQ) || (op == iFCOProp::OP_NE)); + + if (IsEqual(*static_cast(rhs))) + return (op == iFCOProp::OP_EQ) ? iFCOProp::CMP_TRUE : iFCOProp::CMP_FALSE; + else + return (op == iFCOProp::OP_NE) ? iFCOProp::CMP_TRUE : iFCOProp::CMP_FALSE; +} + + +void cArchiveSigGen::AddSig( iSignature* pSig ) +{ + mSigList.push_back( pSig ); +} + +void cArchiveSigGen::CalculateSignatures( cArchive& a ) +{ + byte abBuf[iSignature::SUGGESTED_BLOCK_SIZE]; + const int cbToRead = iSignature::SUGGESTED_BLOCK_SIZE; + int cbRead; + container_type::size_type i; + + // init hash + for( i = 0; i < mSigList.size(); i++ ) + mSigList[i]->Init(); + + // hash data + do + { + cbRead = a.ReadBlob( abBuf, cbToRead ); + + for( i = 0; i < mSigList.size(); i++ ) + mSigList[i]->Update( abBuf, cbRead ); + } + while( cbRead == cbToRead ); + + // finalize hash + for( i = 0; i < mSigList.size(); i++ ) + mSigList[i]->Finit(); +} + +/////////////////////////////////////////////////////////////////////////////// +// btob64 -- convert arbitrary bits to base 64 string +// +// Input: bit array (represented as u_char array) +// number of bits in the array +// ptr-to-str for return string val +/////////////////////////////////////////////////////////////////////////////// +char* btob64(const register byte* pcbitvec, register char* pcout, int numbits) +{ + register unsigned int val; + register int offset; + uint8 *pcorig = (uint8 *) pcout; + + ASSERT( sizeof( uint8 ) == sizeof( byte ) ); /* everything breaks otherwise */ + assert(numbits > 0); + + val = *pcbitvec; + + offset = numbits % 6; /* how many bits initially? */ + if (offset) + { + val >>= (8 - offset); + *pcout++ = base64vec[val & 0x1f]; + } + + for ( numbits -= offset; numbits > 0; offset += 6, numbits -= 6) + { + val = *pcbitvec; + if (offset > 2) + { + offset -= 8; + val <<= 8; + val |= *++pcbitvec; + } + val >>= (2-offset); + + *pcout++ = base64vec[val & 0x3f]; + } + + *pcout = '\0'; + + return (char *) pcorig; +} + +/////////////////////////////////////////////////////////////////////////////// +// pltob64 -- walk through a vector of int32s, convert them to +// network byte ordering, and then convert to base 64 +// this is the preferred interface to btob64. +/////////////////////////////////////////////////////////////////////////////// + +#define NUMTMPLONGS 1000 +char* pltob64(uint32* pl, char* pcout, int numlongs) +{ + register int i; + register uint32 *plto; + uint32 larray[NUMTMPLONGS]; + + assert(numlongs < NUMTMPLONGS); + /* we use our own ntohl() routines, but we have to do it in-place */ + memcpy((char *) larray, (char *) pl, numlongs*sizeof(uint32)); + + for (i = 0, plto = larray; i < numlongs; i++) { + *plto = tw_htonl(*plto); + ++plto; + } + + return btob64((byte*) larray, (char *) pcout, numlongs*sizeof(uint32)*8); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cNullSignature -- The signature that is always 0 +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cNullSignature, _T("cNullSignature"), 0, 1) + +cNullSignature::cNullSignature() +{ +} + +cNullSignature::~cNullSignature() +{ +} + +void cNullSignature::Init() +{ +} + +void cNullSignature::Update( const byte* pbData, int cbDataLen ) +{ +} + +void cNullSignature::Finit() +{ +} + +TSTRING cNullSignature::AsString() const +{ + TSTRING s = _T("0"); + return s; +} + +TSTRING cNullSignature::AsStringHex() const +{ + TSTRING s = _T("0"); + return s; +} + + +bool cNullSignature::IsEqual(const iSignature& rhs) const +{ + return true; +} + +void cNullSignature::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Null Signature Read"))); + +#ifdef _DEBUG + int16 ret; + pSerializer->ReadInt16(ret); + ASSERT(ret == 123); +#endif +} + +void cNullSignature::Write(iSerializer* pSerializer) const +{ +#ifdef _DEBUG + pSerializer->WriteInt16(123); +#endif +} + + +/////////////////////////////////////////////////////////////////////////////// +// Copy +/////////////////////////////////////////////////////////////////////////////// +void cNullSignature::Copy(const iFCOProp* rhs) +{ + // do nothing! +} + + +/////////////////////////////////////////////////////////////////////////////// +// class cChecksumSignature -- A simple signature consisting of all the bytes +// in an archive. Useful as an example if nothing else. +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cChecksumSignature, _T("cChecksumSignature"), 0, 1) + +cChecksumSignature::cChecksumSignature() +{ + mChecksum = 0; +} + +cChecksumSignature::~cChecksumSignature() +{ + +} + +void cChecksumSignature::Init() +{ +} + +void cChecksumSignature::Update( const byte* pbData, int cbDataLen ) +{ + for( int i = 0; i < cbDataLen; i++, pbData++ ) + mChecksum += *pbData; +} + +void cChecksumSignature::Finit() +{ +} + + +TSTRING cChecksumSignature::AsString() const +{ + TSTRING ret; + char *ps_signature; + char buf[100]; + uint32 local[2]; + local[0] = (uint32)(mChecksum >> 32); // note we put the MSB first + local[1] = (uint32)(mChecksum); + + ps_signature = pltob64(local, buf, 2); + //ps_signature holds base64 representation of mCRC +#ifdef _UNICODE + ret.resize(strlen(ps_signature)); + mbstowcs((TCHAR*)ret.data(), ps_signature, strlen(ps_signature)); +#else + ret.append(ps_signature); +#endif + return ret; +} + +TSTRING cChecksumSignature::AsStringHex() const +{ + TOSTRINGSTREAM ss; + + ss.imbue( std::locale::classic() ); + ss.setf( ios::hex, ios::basefield ); + + ASSERT( false ); + ss << (size_t)(uint32) mChecksum; // TODO:BAM -- this is truncating a 64-bit value to 32 bits! + + return ss.str(); +} + +bool cChecksumSignature::IsEqual(const iSignature& rhs) const +{ + return mChecksum == ((cChecksumSignature&)rhs).mChecksum; +} + +void cChecksumSignature::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Checksum Signature Read"))); + + pSerializer->ReadInt64((int64&)mChecksum); +} + +void cChecksumSignature::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt64((int64)mChecksum); +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy +/////////////////////////////////////////////////////////////////////////////// +void cChecksumSignature::Copy(const iFCOProp* rhs) +{ + ASSERT(GetType() == rhs->GetType()); + mChecksum = static_cast(rhs)->mChecksum; +} + +/////////////////////////////////////////////////////////////////////////////// +// class cCRC32Signature -- A CRC32 signature +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cCRC32Signature, _T("cCRC32Signature"), 0, 1); + +cCRC32Signature::cCRC32Signature() +{ +} + +cCRC32Signature::~cCRC32Signature() +{ +} + +void cCRC32Signature::Init() +{ + crcInit( mCRCInfo ); +} + +void cCRC32Signature::Update( const byte* pbData, int cbDataLen ) +{ + ASSERT( sizeof( byte ) == sizeof( uint8 ) ); + crcUpdate( mCRCInfo, (uint8*)pbData, cbDataLen ); +} + +void cCRC32Signature::Finit() +{ + crcFinit( mCRCInfo ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AsString -- Returns a TSTRING that holds the base64 representation of +// mCRC +TSTRING cCRC32Signature::AsString() const +{ + TSTRING ret; + char *ps_signature; + char buf[100]; + uint32 local = mCRCInfo.crc; + + ps_signature = pltob64(&local, buf, 1); + //ps_signature holds base64 representation of mCRCInfo.crc +#ifdef _UNICODE + ret.resize(strlen(ps_signature)); + mbstowcs((TCHAR*)ret.data(), ps_signature, strlen(ps_signature)); +#else + ret.append(ps_signature); +#endif + return ret; +} + +TSTRING cCRC32Signature::AsStringHex() const +{ + TOSTRINGSTREAM ss; + + ss.imbue( std::locale::classic() ); + ss.setf( ios::hex, ios::basefield ); + + ss << (size_t)mCRCInfo.crc; + + return ss.str(); +} + +bool cCRC32Signature::IsEqual(const iSignature& rhs) const +{ + if (this == &rhs) + return true; + else + return (mCRCInfo.crc == ((cCRC32Signature&)rhs).mCRCInfo.crc); +} + +void cCRC32Signature::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("CRC32 Read"))); + + pSerializer->ReadInt32((int32&)mCRCInfo.crc); +} + +void cCRC32Signature::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteInt32((int32)mCRCInfo.crc); +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy +/////////////////////////////////////////////////////////////////////////////// +void cCRC32Signature::Copy(const iFCOProp* rhs) +{ + ASSERT(GetType() == rhs->GetType()); + mCRCInfo.crc = static_cast(rhs)->mCRCInfo.crc; +} + +/////////////////////////////////////////////////////////////////////////////// +// class cMD5Signature -- A MD5 signature +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cMD5Signature, _T("cMD5Signature"), 0, 1) + +cMD5Signature::cMD5Signature() +{ + memset( mMD5Info.digest, 0, sizeof( mMD5Info.digest ) ); + memset( md5_digest, 0, MD5_DIGEST_LENGTH ); +} + +cMD5Signature::~cMD5Signature() +{ +} + +void cMD5Signature::Init() +{ +#ifdef HAVE_OPENSSL_MD5_H + MD5_Init( &mMD5Info ); +#else + MD5Init( &mMD5Info ); +#endif +} + +void cMD5Signature::Update( const byte* pbData, int cbDataLen ) +{ +#ifdef HAVE_OPENSSL_MD5_H + MD5_Update( &mMD5Info, (uint8*)pbData, cbDataLen ); +#else + MD5Update( &mMD5Info, (uint8*)pbData, cbDataLen ); +#endif +} + +void cMD5Signature::Finit() +{ +#ifdef HAVE_OPENSSL_MD5_H + MD5_Final( md5_digest, &mMD5Info ); +#else + MD5Final( &mMD5Info ); + bcopy(mMD5Info.digest, md5_digest, MD5_DIGEST_LENGTH); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// AsString -- Converts to Base64 representation and returns a TSTRING +TSTRING cMD5Signature::AsString() const +{ + TSTRING ret; + char buf[24]; + int length; + + ASSERT( sizeof( uint8 ) == sizeof( byte ) ); /* everything breaks otherwise */ + btob64((byte*)md5_digest, buf, SIG_BYTE_SIZE*8); + //converting to base64 representation. + length = strlen(buf); + +#ifdef _UNICODE //making it TSTRING sensitive + ret.resize(length); + mbstowcs((TCHAR*) ret.data(), buf, length); +#else + ret.append(buf); +#endif + return ret; + //return ret; + //ret holds base64 representation of digest. +} + +TSTRING cMD5Signature::AsStringHex() const +{ + TSTRING ret; + + TCHAR stringBuffer[128]; + TCHAR sigStringOut[128]; + sigStringOut[0] = '\0'; + uint8 *dbuf = (uint8 *)md5_digest; + + for(int i = 0; i < SIG_BYTE_SIZE; ++i) + { + _stprintf(stringBuffer, _T("%02lx"), dbuf[i]); + _tcscat(sigStringOut, stringBuffer); + } + ret.append(sigStringOut); + + return ret; +} + +bool cMD5Signature::IsEqual(const iSignature& rhs) const +{ + if (this == &rhs) + return true; + else { + return (memcmp(md5_digest, ((cMD5Signature&)rhs).md5_digest, SIG_BYTE_SIZE) == 0); + } +} + +void cMD5Signature::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("MD5 Read"))); + + pSerializer->ReadBlob(md5_digest, SIG_BYTE_SIZE); +} + +void cMD5Signature::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteBlob(md5_digest, SIG_BYTE_SIZE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy +/////////////////////////////////////////////////////////////////////////////// +void cMD5Signature::Copy(const iFCOProp* rhs) +{ + ASSERT(GetType() == rhs->GetType()); + memcpy(md5_digest, &(static_cast(rhs)->md5_digest), SIG_BYTE_SIZE); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cSHASignature -- Implementation for cSHASignature: +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cSHASignature, _T("cSHASignature"), 0, 1) + +cSHASignature::cSHASignature() +{ + memset( &mSHAInfo, 0, sizeof( mSHAInfo ) ); + memset( sha_digest, 0, SHA_DIGEST_LENGTH ); +} + +cSHASignature::~cSHASignature() +{} + +void cSHASignature::Init() +{ +#ifdef HAVE_OPENSSL_SHA_H + SHA1_Init( &mSHAInfo ); +#else + shsInit( &mSHAInfo ); +#endif +} + +void cSHASignature::Update( const byte* pbData, int cbDataLen ) +{ + ASSERT( sizeof( byte ) == sizeof( uint8 ) ); +#ifdef HAVE_OPENSSL_SHA_H + SHA1_Update( &mSHAInfo, (uint8*)pbData, cbDataLen ); +#else + shsUpdate( &mSHAInfo, (uint8*)pbData, cbDataLen ); +#endif +} + +void cSHASignature::Finit() +{ +#ifdef HAVE_OPENSSL_SHA_H + SHA1_Final( (unsigned char *)sha_digest, &mSHAInfo ); +#else + shsFinal( &mSHAInfo ); + bcopy(&mSHAInfo.digest, sha_digest, SHA_DIGEST_LENGTH); + { + /* sha_digest is a byte array, so can't be in + * host order. + */ + int i; + uint32 *j = (uint32 *)sha_digest; + uint32 *k = (uint32 *)&mSHAInfo.digest; + for(int i=0; i> 8) & 0xff00 ) | ( (k[i] >> 24) & 0x00ff ); +# endif //WORDS_BIGENDIAN + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// AsString -- Converts to Base64 representation and returns a TSTRING +TSTRING cSHASignature::AsString(void) const +{ + TSTRING ret; + char* ps_signature; + char buf[100]; + int length; + + ps_signature = btob64((uint8*)sha_digest, buf, SIG_UINT32_SIZE*sizeof(uint32)*8); + //converting to base64 representation. + length = strlen(ps_signature); + +#ifdef _UNICODE //making it TSTRING sensitive + ret.resize(length); + mbstowcs((TCHAR*) ret.data(), ps_signature, length); +#else + ret.append(ps_signature); +#endif + return ret; + //return ret; +} + +TSTRING cSHASignature::AsStringHex() const +{ + TSTRING ret; + + TCHAR stringBuffer[128]; + TCHAR sigStringOut[128]; + sigStringOut[0] = '\0'; + uint8 *dbuf = (uint8 *)sha_digest; + + for (int i=0; i < SIG_UINT32_SIZE*(int)sizeof(uint32); ++i) + { + _stprintf(stringBuffer, _T("%02x"), dbuf[i]); + _tcscat(sigStringOut, stringBuffer); + } + ret.append(sigStringOut); + + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy -- Copies a new sig value from a base pointer +void cSHASignature::Copy(const iFCOProp* rhs) +{ + ASSERT(GetType() == rhs->GetType()); + for (int i = 0; i(rhs))->mSHAInfo.digest)[i]; +} + +/////////////////////////////////////////////////////////////////////////////// +// Serializer Implementation: Read and Write +void cSHASignature::Read (iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("SHA Read"))); + + for (int i = 0; i < SIG_UINT32_SIZE; ++i) + pSerializer->ReadInt32((int32&)mSHAInfo.digest[i]); +} + +void cSHASignature::Write(iSerializer* pSerializer) const +{ + for (int i = 0; i < SIG_UINT32_SIZE; ++i) + pSerializer->WriteInt32(mSHAInfo.digest[i]); +} + +/////////////////////////////////////////////////////////////////////////////// +// IsEqual -- Tests for equality, given a base pointer (iSignature) +bool cSHASignature::IsEqual(const iSignature& rhs) const +{ + if (this == &rhs) + return true; + else { + return (memcmp(mSHAInfo.digest, ((cSHASignature&)rhs).mSHAInfo.digest, SIG_UINT32_SIZE * sizeof(uint32)) == 0); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// class cHAVALSignature -- +/////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_TYPEDSERIALIZABLE(cHAVALSignature, _T("cHAVALSignature"), 0, 1) + +cHAVALSignature::cHAVALSignature() +{ + memset( mSignature, 0, sizeof( mSignature ) ); +} + +cHAVALSignature::~cHAVALSignature() +{} + + +void cHAVALSignature::Init() +{ + haval_start( &mHavalState ); +} + +void cHAVALSignature::Update( const byte* pbData, int cbDataLen ) +{ + haval_hash( &mHavalState, (uint8*)pbData, cbDataLen ); +} + +void cHAVALSignature::Finit() +{ + haval_end( &mHavalState, mSignature ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AsString -- Returns Base64 representation of mSignature in a TSTRING +TSTRING cHAVALSignature::AsString() const +{ + TSTRING ret; + char buf[24]; + int length; + + btob64((byte*)mSignature, buf, 128); + //converting to base64 representation. + length = strlen(buf); + +#ifdef _UNICODE //making it TSTRING sensitive + ret.resize(length); + mbstowcs((TCHAR*) ret.data(), buf, length); +#else + ret.append(buf); +#endif + return ret; + //return ret; + //ret holds base64 representation of digest. +} + +TSTRING cHAVALSignature::AsStringHex() const +{ + TSTRING ret; + + TCHAR stringBuffer[128]; + TCHAR sigStringOut[128]; + sigStringOut[0] = _T('\0'); + + for (int i=0; i < SIG_BYTE_SIZE; ++i) + { + _stprintf(stringBuffer, _T("%02x"), mSignature[i]); + _tcscat(sigStringOut, stringBuffer); + } + ret.append(sigStringOut); + + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// Copy -- Copies the sig value using a base class pointer. +void cHAVALSignature::Copy(const iFCOProp* rhs) +{ + ASSERT(GetType() == rhs->GetType()); + memcpy(&mSignature, &(static_cast(rhs)->mSignature), SIG_BYTE_SIZE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Serializer Implementation: Read and Write +void cHAVALSignature::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("HAVAL Read"))); + + pSerializer->ReadBlob(mSignature, SIG_BYTE_SIZE); +} + +void cHAVALSignature::Write(iSerializer* pSerializer) const +{ + pSerializer->WriteBlob(mSignature, SIG_BYTE_SIZE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Equal -- Tests for equality given a base pointer. +bool cHAVALSignature::IsEqual(const iSignature & rhs) const +{ + if (this == &rhs) + return true; + else { + return (memcmp(mSignature, ((cHAVALSignature&)rhs).mSignature, SIG_BYTE_SIZE) == 0); + } +} diff --git a/src/fco/signature.h b/src/fco/signature.h new file mode 100644 index 0000000..8768c29 --- /dev/null +++ b/src/fco/signature.h @@ -0,0 +1,335 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// signature.h -- interface for calculating file signatures +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __SIGNATURE_H +#define __SIGNATURE_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __FCOPROP_H +#include "fcoprop.h" +#endif + +#include +#include "core/crc32.h" + +#ifdef HAVE_OPENSSL_MD5_H +# include +# define digest data +#else +# include "core/md5.h" +# ifndef MD5_DIGEST_LENGTH +# define MD5_DIGEST_LENGTH 16 +# endif +#endif + +#ifdef HAVE_OPENSSL_SHA_H +# include +#else +# include "core/sha.h" +# define SHA_CTX SHS_INFO +# ifndef SHA_DIGEST_LENGTH +# define SHA_DIGEST_LENGTH 20 +# endif +#endif + +#include "core/haval.h" +// TODO: figure out a way to do this without including these headers. +// pool of objects? + +/////////////////////////////////////////////////////////////////////////////// +// class iSignatrue -- Interface all signatures will implement. +/////////////////////////////////////////////////////////////////////////////// + +class iSignature : public iFCOProp +{ +public: + // + // ctors and dtors + // + virtual ~iSignature() {}; + iSignature() {}; + + // + // enums + // + enum { SUGGESTED_BLOCK_SIZE = 0x1000 }; // best size of block to hash at a time + + // + // basic functionality + // + virtual void Init () = 0; + // call before beginning hashing + virtual void Update( const byte* pbData, int cbDataLen ) = 0; + // may be called multiple times -- best to call with blocks of size SUGGESTED_BLOCK_SIZE, + // but can handle any size data. + virtual void Finit () = 0; + // call to finish hashing + + virtual TSTRING AsStringHex() const = 0; + + // + // from iFCOProp + // + virtual CmpResult Compare( const iFCOProp* rhs, Op op ) const; + +protected: + + // + // don't let C++ create these functions + // + iSignature( const iSignature& ); + iSignature& operator=( const iSignature& ); + + // + // private util functions + // + virtual bool IsEqual( const iSignature& rhs ) const = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// class cArchiveSigGen -- utility class to facilitate archive hashing +// +// Stores a list of signatures (added by AddSig()), and when +// CalculateSignatures is called, makes ONE sweep through the archive, +// calculating hashes for all signatures in the list. +/////////////////////////////////////////////////////////////////////////////// +class cArchiveSigGen +{ +public: + cArchiveSigGen() {}; + + void AddSig( iSignature* pSig ); + // adds a signature to the list + + void CalculateSignatures( cArchive& a ); + // produces signature of archive for all signatures in the list + // remember to rewind archive! + +private: + // don't let C++ create these functions + cArchiveSigGen( const cArchiveSigGen& ); + cArchiveSigGen& operator=( const cArchiveSigGen& ); + + typedef std::vector< iSignature* > container_type; + container_type mSigList; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// class cNullSignature -- The signature that is always 0 +/////////////////////////////////////////////////////////////////////////////// + +class cNullSignature : public iSignature +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cNullSignature(); + virtual ~cNullSignature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + virtual bool IsEqual(const iSignature& rhs) const; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cChecksumSignature -- A simple signature consisting of all the bytes +// in an archive. Useful as an example if nothing else. +/////////////////////////////////////////////////////////////////////////////// + +class cChecksumSignature : public iSignature +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cChecksumSignature(); + virtual ~cChecksumSignature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + virtual bool IsEqual(const iSignature& rhs) const; + + uint64 mChecksum; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cCRC32Signature -- A CRC32 signature +/////////////////////////////////////////////////////////////////////////////// + +class cCRC32Signature : public iSignature +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cCRC32Signature(); + virtual ~cCRC32Signature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + virtual bool IsEqual(const iSignature& rhs) const; + + CRC_INFO mCRCInfo; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cMD5Signature -- A MD5 signature +/////////////////////////////////////////////////////////////////////////////// + +class cMD5Signature : public iSignature +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cMD5Signature(); + virtual ~cMD5Signature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +protected: + enum { SIG_BYTE_SIZE = MD5_DIGEST_LENGTH }; + + virtual bool IsEqual(const iSignature& rhs) const; + MD5_CTX mMD5Info; + uint8 md5_digest[MD5_DIGEST_LENGTH]; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cSHASignature -- A "Secure Hash Algorithm" signature +/////////////////////////////////////////////////////////////////////////////// +class cSHASignature : public iSignature +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cSHASignature(); + virtual ~cSHASignature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read (iSerializer* pSerializer, int32 version = 0); + virtual void Write(iSerializer* pSerializer) const; + +protected: + enum { SIG_UINT32_SIZE = SHA_DIGEST_LENGTH/4 }; + + SHA_CTX mSHAInfo; + + virtual bool IsEqual(const iSignature& rhs) const; + uint32 sha_digest[SHA_DIGEST_LENGTH/4]; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cHAVALSignature -- +/////////////////////////////////////////////////////////////////////////////// +class cHAVALSignature : public iSignature +{ + + DECLARE_TYPEDSERIALIZABLE() + +public: + cHAVALSignature(); + virtual ~cHAVALSignature(); + + virtual void Init (); + virtual void Update( const byte* pbData, int cbDataLen ); + virtual void Finit (); + virtual TSTRING AsString() const; + virtual TSTRING AsStringHex() const; + virtual void Copy(const iFCOProp* rhs); + + virtual void Read(iSerializer* pSerializer, int32 version = 0); + virtual void Write(iSerializer* pSerializer) const; + +protected: + enum { SIG_BYTE_SIZE = 16 }; + + virtual bool IsEqual(const iSignature& rhs) const; + + haval_state mHavalState; + uint8 mSignature[SIG_BYTE_SIZE]; + +}; + +#endif // __SIGNATURE_H + diff --git a/src/fco/signature_t.cpp b/src/fco/signature_t.cpp new file mode 100644 index 0000000..1f55321 --- /dev/null +++ b/src/fco/signature_t.cpp @@ -0,0 +1,364 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// + +#include "stdfco.h" +#include +#include +#include "signature.h" +#include "core/tchar.h" +#include "test/test.h" +#include "core/errorgeneral.h" +#include "core/serializerimpl.h" +#include "core/crc32.h" +#include "core/archive.h" + +using namespace std; + +void TestSignature() +{ + // Signature usage example (?) + cCRC32Signature crcSig; + cDebug d("TestSignature"); + + byte abData[ 64 ]; + int i; + for( i = 0; i < 64; i++ ) + abData[i] = static_cast< byte >( rand() ); + + crcSig.Init(); + crcSig.Update( &abData[0], 32 ); + crcSig.Update( &abData[32], 32 ); + crcSig.Finit(); + TCOUT << _T("new way: ") << crcSig.AsString() << endl; + + cMemoryArchive arch; + arch.WriteBlob( &abData[0], 32 ); + arch.WriteBlob( &abData[32], 32 ); + arch.Seek( 0, cBidirArchive::BEGINNING ); + cCRC32Signature crc; + cArchiveSigGen asg; + asg.AddSig( &crc ); + asg.CalculateSignatures( arch ); + + TCOUT << _T("old way: ") << crc.AsString() << endl; + + + // Note: The following causes an ASSERT() in iSignature::Compare(), as it should, but + // we don't want asserts to occur in a working test suite! +// TEST(nullSig.Compare(&checksumSig, iFCOProp::OP_EQ) == iFCOProp::CMP_WRONG_PROP_TYPE); + + + + // Create a file for which we know the signatures + // + //% siggen ~/signature_test.bin + //crc : AAAAAAAAAAy + //md5 : B/Y8ttBnlyw/NPCUu353ao + //crc32 : B1kP9v + //sha : Oia1aljHD793tfj7M55tND+3OG/ + //haval : BL6bFSo0EP5zf8lGSueeed + + TSTRING sigFileName = TEMP_DIR; + sigFileName += TSTRING( _T("/signature_test.bin") ); + + cFileArchive fileArc; + fileArc.OpenReadWrite(sigFileName.c_str()); + fileArc.WriteBlob("\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0", 10); + fileArc.Close(); + + + // test begins here + + // general signature & archive variables + byte abBuf[iSignature::SUGGESTED_BLOCK_SIZE]; + const int cbToRead = iSignature::SUGGESTED_BLOCK_SIZE; + int cbRead; + + + // test checksum + cChecksumSignature check1, check2; + d.TraceDetail("Testing checksum.\n"); + + // check1 + fileArc.OpenRead(sigFileName.c_str()); + check1.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + check1.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + check1.Finit(); + fileArc.Close(); + + // check2 + fileArc.OpenRead(sigFileName.c_str()); + check2.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + check2.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + check2.Finit(); + fileArc.Close(); + + // compare to each other and the known values + TEST(check1.Compare(&check2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + TEST(check1.AsString().compare(_T("AAAAAAAAAAt")) == 0); + + // test write capabilities + { + cMemoryArchive sigArchive; + cSerializerImpl writeSer(sigArchive, cSerializerImpl::S_WRITE); + check1.Write(&writeSer); + sigArchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(sigArchive, cSerializerImpl::S_READ); + check2.Read(&readSer); + TEST(check1.Compare(&check2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + } + + + // test CRC32 + cCRC32Signature crc1, crc2; + d.TraceDetail("Testing CRC32.\n"); + + // crc1 + fileArc.OpenRead(sigFileName.c_str()); + crc1.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + crc1.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + crc1.Finit(); + fileArc.Close(); + + // crc2 + fileArc.OpenRead(sigFileName.c_str()); + crc2.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + crc2.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + crc2.Finit(); + fileArc.Close(); + + // compare to each other and the known values + TEST(crc1.Compare(&crc2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + TEST(crc1.AsString().compare(_T("B1kP9v")) == 0); + TEST(crc1.AsStringHex().compare(_T("7590ff6f")) == 0); + + // test write capabilities + { + cMemoryArchive sigArchive; + cSerializerImpl writeSer(sigArchive, cSerializerImpl::S_WRITE); + crc1.Write(&writeSer); + sigArchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(sigArchive, cSerializerImpl::S_READ); + crc2.Read(&readSer); + TEST(crc1.Compare(&crc2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + } + + + // test MD5 + cMD5Signature md51, md52; + d.TraceDetail("Testing MD5.\n"); + + // md51 + fileArc.OpenRead(sigFileName.c_str()); + md51.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + md51.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + md51.Finit(); + fileArc.Close(); + + // md52 + fileArc.OpenRead(sigFileName.c_str()); + md52.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + md52.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + md52.Finit(); + fileArc.Close(); + + // compare to each other and the known values + TEST(md51.Compare(&md52, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + TEST(md51.AsString().compare(_T("B/Y8ttBnlyw/NPCUu353ao")) == 0); + TEST(md51.AsStringHex().compare(_T("7f63cb6d067972c3f34f094bb7e776a8")) == 0); + + // test write capabilities + { + cMemoryArchive sigArchive; + cSerializerImpl writeSer(sigArchive, cSerializerImpl::S_WRITE); + md51.Write(&writeSer); + sigArchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(sigArchive, cSerializerImpl::S_READ); + md52.Read(&readSer); + TEST(md51.Compare(&md52, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + } + + + // test SHA + cSHASignature sha1, sha2; + d.TraceDetail("Testing SHA.\n"); + + // sha1 + fileArc.OpenRead(sigFileName.c_str()); + sha1.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + sha1.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + sha1.Finit(); + fileArc.Close(); + + // sha2 + fileArc.OpenRead(sigFileName.c_str()); + sha2.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + sha2.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + sha2.Finit(); + fileArc.Close(); + + // compare to each other and the known values + TEST(sha1.Compare(&sha2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + TEST(sha1.AsString().compare(_T("Oia1aljHD793tfj7M55tND+3OG/")) == 0); + TEST(sha1.AsStringHex().compare(_T("e89ad5a9631c3efdded7e3ecce79b4d0fedce1bf")) == 0); + + // test write capabilities + { + cMemoryArchive sigArchive; + cSerializerImpl writeSer(sigArchive, cSerializerImpl::S_WRITE); + sha1.Write(&writeSer); + sigArchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(sigArchive, cSerializerImpl::S_READ); + sha2.Read(&readSer); + TEST(sha1.Compare(&sha2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + } + + + // test HAVAL + cHAVALSignature haval1, haval2; + d.TraceDetail("Testing HAVAL.\n"); + + // haval1 + fileArc.OpenRead(sigFileName.c_str()); + haval1.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + haval1.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + haval1.Finit(); + fileArc.Close(); + + // haval2 + fileArc.OpenRead(sigFileName.c_str()); + haval2.Init(); + do + { + cbRead = fileArc.ReadBlob( abBuf, cbToRead ); + haval2.Update( abBuf, cbRead ); + } + while ( cbRead == cbToRead ); + haval2.Finit(); + fileArc.Close(); + + // compare to each other and the known values + TEST(haval1.Compare(&haval2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + TEST(haval1.AsString().compare(_T("BL6bFSo0EP5zf8lGSueeed")) == 0); + TEST(haval1.AsStringHex().compare(_T("4be9b152a3410fe737fc9464ae79e79d")) == 0); + + // test write capabilities + { + cMemoryArchive sigArchive; + cSerializerImpl writeSer(sigArchive, cSerializerImpl::S_WRITE); + haval1.Write(&writeSer); + sigArchive.Seek(0, cBidirArchive::BEGINNING); + cSerializerImpl readSer(sigArchive, cSerializerImpl::S_READ); + md52.Read(&readSer); + TEST(haval1.Compare(&haval2, iFCOProp::OP_EQ) == iFCOProp::CMP_TRUE); + } + + + // test cArchiveSigGen + cArchiveSigGen asgtest; + cCRC32Signature crc3; + cMD5Signature md53; + cSHASignature sha3; + cHAVALSignature haval3; + d.TraceDetail("Testing cArchiveSigGen\n"); + + asgtest.AddSig( &crc3 ); + asgtest.AddSig( &md53 ); + asgtest.AddSig( &sha3 ); + asgtest.AddSig( &haval3 ); + + // calculate the signatures + fileArc.OpenRead(sigFileName.c_str()); + fileArc.Seek( 0, cBidirArchive::BEGINNING ); + + asgtest.CalculateSignatures( fileArc ); + + // compare to known values + TEST(crc3.AsString().compare(_T("B1kP9v")) == 0); + TEST(crc3.AsStringHex().compare(_T("7590ff6f")) == 0); + TEST(md53.AsString().compare(_T("B/Y8ttBnlyw/NPCUu353ao")) == 0); + TEST(md53.AsStringHex().compare(_T("7f63cb6d067972c3f34f094bb7e776a8")) == 0); + TEST(sha3.AsString().compare(_T("Oia1aljHD793tfj7M55tND+3OG/")) == 0); + TEST(sha3.AsStringHex().compare(_T("e89ad5a9631c3efdded7e3ecce79b4d0fedce1bf")) == 0); + TEST(haval3.AsString().compare(_T("BL6bFSo0EP5zf8lGSueeed")) == 0); + TEST(haval3.AsStringHex().compare(_T("4be9b152a3410fe737fc9464ae79e79d")) == 0); + + fileArc.Close(); + + return; +} + diff --git a/src/fco/stdfco.cpp b/src/fco/stdfco.cpp new file mode 100644 index 0000000..6d6acbc --- /dev/null +++ b/src/fco/stdfco.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdfco.cpp +// Date....: 05/07/99 +// Creator.: Robert DiFalco (rdifalco) +// + +#include "stdfco.h" + +// eof: stdfco.cpp diff --git a/src/fco/stdfco.h b/src/fco/stdfco.h new file mode 100644 index 0000000..f897a01 --- /dev/null +++ b/src/fco/stdfco.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdfco.h +// +// Standard includes for fco +// + +#include "core/stdcore.h" + diff --git a/src/fco/twfactory.cpp b/src/fco/twfactory.cpp new file mode 100644 index 0000000..627a632 --- /dev/null +++ b/src/fco/twfactory.cpp @@ -0,0 +1,51 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twfactory.cpp +// +#include "stdfco.h" +#include "twfactory.h" + +iTWFactory* iTWFactory::mpInstance = 0; + +void iTWFactory::SetFactory(iTWFactory* pFact) +{ + mpInstance = pFact; +} + +iTWFactory* iTWFactory::GetInstance() +{ + // TODO -- should I assert(mpInstance)? That is, is it an error condition to ask for + // the instance before it has been set? + return mpInstance; +} + diff --git a/src/fco/twfactory.h b/src/fco/twfactory.h new file mode 100644 index 0000000..964dd96 --- /dev/null +++ b/src/fco/twfactory.h @@ -0,0 +1,106 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twfactory.h +// +// iTWFactory -- an interface for classes that use the abstract factory pattern +// to provide the appropriate instances of classes +#ifndef __TWFACTORY_H +#define __TWFACTORY_H + +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" +#endif + +class iFCOPropCalc; +class iFCOSpec; +class iFCOSpecHelper; +class iFCOPropDisplayer; +class iParserGenreUtil; +class cFCOSetWS; +class iFCODataSourceIter; +class iFCONameInfo; +class cFCOPropVector; +class iFCONameTranslator; + +// NOTE -- all the pointers returned from this factory should be deleted after usage +class iTWFactory +{ +public: + static void SetFactory(iTWFactory* pFact); + // sets the single instance of the tripwire factory to what was passed it. The caller + // is responsible for deleting the pointer. (probably just created on the stack.) + static iTWFactory* GetInstance(); + // returns the global instance of the tripwire factory + + virtual iFCOPropCalc* CreatePropCalc() const = 0; + // returns an object that can calculate properties for fcos produced by the + // DataSource. + virtual iFCOSpec* CreateSpec(const TSTRING& name, iFCOSpecHelper* pHelper = NULL) const = 0; + // creates an appropriate FCOSpec and assignes it the name and helper specified. + + virtual iFCOPropDisplayer* CreatePropDisplayer() const = 0; + // returns a pointer to an object which knows how to display human-readable representations of an FCO's properties + + virtual iSerRefCountObj::CreateFunc GetCreateFunc() const = 0; + // returns a pointer to a function that creates instances of the currently appropriate FCO. + + virtual iParserGenreUtil* CreateParserGenreUtil() const = 0; + // returns a pointer to an object that handles all genre-dependant parser functions for the currently appropriate FCO. + + virtual iFCODataSourceIter* CreateDataSourceIter() const = 0; + + virtual iFCONameInfo* GetNameInfo() const = 0; + // returns a pointer to a class that provides characteristics of the FCO's names in the + // current genre. Since this class will have no data, the object returned should be declared + // statically in the cpp file that implements this method, so: + // NOTE -- do _not_ delete the pointer you get back from calling this method!! + + virtual cFCOPropVector GetLooseDirMask() const = 0; + // ok, it sucks that this interface is polluted with this method, but I can't really come up with a + // better place for this. + // + // the property vector returned from this method indicates what properties should be _ignored_ for + // an integrity check run in "loose directory" mode. This mask will be stripped off of all fcos comapred + // where both return CAP_CAN_HAVE_CHILDREN from iFCO::GetCaps() + + virtual iFCONameTranslator* GetNameTranslator() const = 0; + + virtual ~iTWFactory() {} + + +private: + static iTWFactory* mpInstance; +}; + +#endif //__TWFACTORY_H + diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am new file mode 100644 index 0000000..e1da0fb --- /dev/null +++ b/src/fs/Makefile.am @@ -0,0 +1,15 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libfs.a +libfs_a_SOURCES = \ + fs.cpp fsdatasourceiter.cpp fserrors.cpp fsfactory.cpp \ + fsnametranslator.cpp fsobject.cpp fsparserutil.cpp \ + fspropcalc.cpp fspropdisplayer.cpp fspropset.cpp \ + fsstrings.cpp fsvisitor.cpp stdfs.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libfs_a_OBJECTS) diff --git a/src/fs/Makefile.in b/src/fs/Makefile.in new file mode 100644 index 0000000..772c595 --- /dev/null +++ b/src/fs/Makefile.in @@ -0,0 +1,404 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libfs_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/fs +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libfs_a_AR = $(AR) $(ARFLAGS) +libfs_a_LIBADD = +am_libfs_a_OBJECTS = fs.$(OBJEXT) fsdatasourceiter.$(OBJEXT) \ + fserrors.$(OBJEXT) fsfactory.$(OBJEXT) \ + fsnametranslator.$(OBJEXT) fsobject.$(OBJEXT) \ + fsparserutil.$(OBJEXT) fspropcalc.$(OBJEXT) \ + fspropdisplayer.$(OBJEXT) fspropset.$(OBJEXT) \ + fsstrings.$(OBJEXT) fsvisitor.$(OBJEXT) stdfs.$(OBJEXT) +libfs_a_OBJECTS = $(am_libfs_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libfs_a_SOURCES) +DIST_SOURCES = $(libfs_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libfs.a +libfs_a_SOURCES = \ + fs.cpp fsdatasourceiter.cpp fserrors.cpp fsfactory.cpp \ + fsnametranslator.cpp fsobject.cpp fsparserutil.cpp \ + fspropcalc.cpp fspropdisplayer.cpp fspropset.cpp \ + fsstrings.cpp fsvisitor.cpp stdfs.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/fs/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/fs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libfs.a: $(libfs_a_OBJECTS) $(libfs_a_DEPENDENCIES) + -rm -f libfs.a + $(libfs_a_AR) libfs.a $(libfs_a_OBJECTS) $(libfs_a_LIBADD) + $(RANLIB) libfs.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libfs_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/fs/fs.cpp b/src/fs/fs.cpp new file mode 100644 index 0000000..27c5f4b --- /dev/null +++ b/src/fs/fs.cpp @@ -0,0 +1,89 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fs.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfs.h" +#include "fs.h" +#include "fserrors.h" +#include "fsfactory.h" +#include "fco/genreswitcher.h" + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + + +#if IS_AIX +// For some stupid linker reason, this object does not get constructed under +// AIX. The cheap fix is to move this call to here from fspropdisplayer.cpp +#include "fspropdisplayer.h" +IMPLEMENT_TYPEDSERIALIZABLE( cFSPropDisplayer, _T("FSPropDisplayer"), 0, 1 ); +#endif + + +TSS_ImplementPackage( cFS ) + +cFS::cFS() + : fsFactory(), + fsGenre( + GenreID(), + _T("FS"), + _T("Unix File System"), + &fsFactory + ) +{ + // + // set up dependencies + // + // TODO:BAM -- TSS_Dependency( ??? ); + + // + // register genre + // + cGenreSwitcher::RegisterFlags flags = cGenreSwitcher::REGISTER_FLAGS_DEFAULT; + + // TODO:BAM -- we include FS in the Win32 build but we don't want + // it to be the default genre for that build + // Remove this ifdef when we remove FS from the Win32 build + cGenreSwitcher::GetInstance()->RegisterGenre( &fsGenre, flags ); + + // register errors... + // + TSS_REGISTER_PKG_ERRORS( fs ) +} + diff --git a/src/fs/fs.h b/src/fs/fs.h new file mode 100644 index 0000000..0a4144c --- /dev/null +++ b/src/fs/fs.h @@ -0,0 +1,68 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +* Name....: fs.h +* Date....: 05/07/99 +* Creator.: Brian McFeely (bmcfeely) +* +* The Package class for the TSS fs library module. +*/ + +#ifndef __FS_H +#define __FS_H + +//--Requirements + +#include "core/package.h" // for: Packaging Abstraction +#include "fco/genreinfo.h" // for: cGenreInfo +#include "fsfactory.h" // for: cFSFactory + +//--Classes + +TSS_BeginPackage( cFS ) + + TSS_DECLARE_STRINGTABLE; + + public: + cFS(); + static cGenre::Genre GenreID() { return GENRE_ID; }; + + private: + enum { GENRE_ID = 0x00020001 }; + + cFSFactory fsFactory; + cGenreInfo fsGenre; + +TSS_EndPackage( cFS ) + +#endif //#ifndef __FS_H + diff --git a/src/fs/fsdatasourceiter.cpp b/src/fs/fsdatasourceiter.cpp new file mode 100644 index 0000000..357ccfd --- /dev/null +++ b/src/fs/fsdatasourceiter.cpp @@ -0,0 +1,260 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsdatasourceiter.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfs.h" + +#include "fsdatasourceiter.h" +#include "fco/fcodatasourceiter.h" +#include "fsobject.h" +#include "core/fsservices.h" +#include "core/errorbucket.h" +#include "core/corestrings.h" +#include "core/usernotify.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" +#include "fco/fconameinfo.h" +#include "fsstrings.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +cFSDataSourceIter::cFSDataSourceIter() +{ + // set the case sensitiveness of the parent... + // + mDev = 0; + mParentName.SetCaseSensitive( iTWFactory::GetInstance()->GetNameInfo()->IsCaseSensitive() ); +} + +cFSDataSourceIter::~cFSDataSourceIter() +{ +} + +cFSDataSourceIter::cFSDataSourceIter( const cFSDataSourceIter& rhs ) +{ + // set the case sensitiveness of the parent... + // + mParentName.SetCaseSensitive( iTWFactory::GetInstance()->GetNameInfo()->IsCaseSensitive() ); + *this = rhs; +} + +/////////////////////////////////////////////////////////////////////////////// +// operator = +/////////////////////////////////////////////////////////////////////////////// +cFSDataSourceIter& cFSDataSourceIter::operator=( const cFSDataSourceIter& rhs ) +{ + if( this == &rhs ) + return *this; + + // copy base + cFCODataSourceIterImpl::operator=(rhs); + // copy derived + mDev = rhs.mDev; + + return *this; +} + +static bool gCrossFileSystems = false; + +// Call this to set the property where cFSDataSourceIter does not automatically recurse +// across file system boundaries. Currently this is by default is set to false. +/*static*/ void cFSDataSourceIter::SetFileSystemCrossing(bool crossFS) +{ + gCrossFileSystems = crossFS; +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateCopy +/////////////////////////////////////////////////////////////////////////////// +iFCODataSourceIter* cFSDataSourceIter::CreateCopy() const +{ + return (new cFSDataSourceIter(*this)); +} + + +/////////////////////////////////////////////////////////////////////////////// +// CreateObject -- creates the named object and fills out its properties +// appropriately. Returns NULL if any errors occur and fills up the +// error queue. +// +// This does not create the object if dev > 0 and the object's mDev is not +// equal to it (thus preventing the crossing of file systems) +// +// TODO -- in the future, this should become some kind of lazy evaluation so +// that we don't have to get all the stats() we don't need to. +/////////////////////////////////////////////////////////////////////////////// +iFCO * cFSDataSourceIter::CreateObject(const cFCOName& name, bool bCreatePeers ) +{ + cFSObject* pNewObj = new cFSObject(name); + + if( ! bCreatePeers ) + { + // when bCreatePeers is false, it means we should set mDev to the + // device number of the current object (ie -- it is a new "start point") + // If we don't do this here, InitializeTypeInfo() will reject creating the + // node. + // -- 9 June 99 mdb + // + mDev = 0; + if( ! InitializeTypeInfo( pNewObj ) ) + { + pNewObj->Release(); + return 0; + } + mDev = pNewObj->GetFSPropSet().GetDev(); + } + + return pNewObj; +} + +void cFSDataSourceIter::GetChildrenNames( const TSTRING& strParentName, std::vector& vChildrenNames ) +{ + try + { + iFSServices::GetInstance()->ReadDir( strParentName, vChildrenNames, false ); + } + catch( eFSServices& e ) + { + cDebug d("cFSDataSourceIter::GeneratePeers"); + d.TraceError("**** ReadDir failed for %s\n", strParentName.c_str() ); + + if( mpErrorBucket ) + { + eFSDataSourceIterReadDir eReadDir(e.GetMsg(), eError::NON_FATAL); + mpErrorBucket->AddError( eReadDir ); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// InitializeTypeInfo +/////////////////////////////////////////////////////////////////////////////// +bool cFSDataSourceIter::InitializeTypeInfo(iFCO* pFCO) +{ + cFSObject* pObj = (cFSObject*)pFCO; + iFCONameTranslator* pTrans = iTWFactory::GetInstance()->GetNameTranslator(); + + if( pObj->GetFSPropSet().GetValidVector().ContainsItem( cFSPropSet::PROP_FILETYPE) ) + return true; + + // + // assume invalid by default... + // + cFSPropSet& propSet = pObj->GetFSPropSet(); + propSet.SetFileType(cFSPropSet::FT_INVALID); + + cFSStatArgs statArgs; + try + { + iFSServices::GetInstance()->Stat( pTrans->ToStringAPI( pObj->GetName() ), statArgs); + } + catch(eFSServices& e) + { + cDebug d("CreateObject"); + d.TraceError( "*** Stat of %s failed!!!\n", pObj->GetName().AsString().c_str() ); + if( mpErrorBucket ) + { + e.SetFatality( false ); + mpErrorBucket->AddError( e ); + } + return false; + } + + // + // don't create the object if it is on a different file system... + // + if( gCrossFileSystems == false && (mDev != 0) && (statArgs.dev != mDev) ) + { + TW_NOTIFY_NORMAL( TSS_GetString( cFS, fs::STR_DIFFERENT_FILESYSTEM ).c_str(), + pTrans->ToStringDisplay( pObj->GetName() ).c_str() ); + return false; + } + + // + // fill out all of the appropriate properties.... + // + propSet.SetDev (statArgs.dev); + propSet.SetRDev (statArgs.rdev); + propSet.SetInode (statArgs.ino); + propSet.SetMode (statArgs.mode); + propSet.SetNLink (statArgs.nlink); + propSet.SetUID (statArgs.uid); + propSet.SetGID (statArgs.gid); + propSet.SetSize (statArgs.size); + propSet.SetAccessTime (statArgs.atime); + propSet.SetModifyTime (statArgs.mtime); + propSet.SetCreateTime (statArgs.ctime); + propSet.SetBlockSize (statArgs.blksize); + propSet.SetBlocks (statArgs.blocks); + propSet.SetGrowingFile (statArgs.size); + + // set the file type + switch(statArgs.mFileType) + { + case cFSStatArgs::TY_FILE: + propSet.SetFileType(cFSPropSet::FT_FILE); + break; + case cFSStatArgs::TY_DIR: + propSet.SetFileType(cFSPropSet::FT_DIR); + break; + case cFSStatArgs::TY_BLOCKDEV: + propSet.SetFileType(cFSPropSet::FT_BLOCKDEV); + break; + case cFSStatArgs::TY_CHARDEV: + propSet.SetFileType(cFSPropSet::FT_CHARDEV); + break; + case cFSStatArgs::TY_SYMLINK: + propSet.SetFileType(cFSPropSet::FT_SYMLINK); + break; + case cFSStatArgs::TY_FIFO: + propSet.SetFileType(cFSPropSet::FT_FIFO); + break; + case cFSStatArgs::TY_SOCK: + propSet.SetFileType(cFSPropSet::FT_SOCK); + break; + default: + // set it to invalid + propSet.SetFileType(cFSPropSet::FT_INVALID); + } + + return true; + +} + diff --git a/src/fs/fsdatasourceiter.h b/src/fs/fsdatasourceiter.h new file mode 100644 index 0000000..99eecda --- /dev/null +++ b/src/fs/fsdatasourceiter.h @@ -0,0 +1,89 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsdatasourceiter.h +// +#ifndef __FSDATASOURCEITER_H +#define __FSDATASOURCEITER_H + +//========================================================================= +// INCLUDES +//========================================================================= +#include "fco/fcodatasourceiterimpl.h" + +TSS_EXCEPTION( eFSDataSourceIter, eError ) +TSS_EXCEPTION( eFSDataSourceIterReadDir, eFSDataSourceIter ) + + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//----------------------------------------------------------------------------- +// *** Important Note: Not crossing file system boundaries works by noting the +// device number of the object created by SeekToFCO( XXX, false ), since it +// is assumed the only time you will pass false is when you are seeking to +// the start point of a spec. +// -- 20 Jan 99 mdb +//----------------------------------------------------------------------------- +class cFSDataSourceIter : public cFCODataSourceIterImpl +{ +public: + cFSDataSourceIter(); + cFSDataSourceIter( const cFSDataSourceIter& rhs ); + virtual ~cFSDataSourceIter(); + + cFSDataSourceIter& operator=( const cFSDataSourceIter& rhs ); + + virtual iFCODataSourceIter* CreateCopy() const; + + static void SetFileSystemCrossing(bool crossFS); + // Call this to set the property where cFSDataSourceIter does not automatically recurse + // across file system boundaries. Currently this is by default is set to false. + + //void TraceContents(int dl = -1) const; +private: + uint64 mDev; // the device number of the last node reached through SeekTo() + // if this is zero, then it is assumed to be uninitialized + + //------------------------------------------------------------------------- + // helper methods + //------------------------------------------------------------------------- + + virtual void GetChildrenNames( const TSTRING& strParentName, std::vector& vChildrenNames ); + + virtual iFCO* CreateObject(const cFCOName& name, bool bCreatingPeers ); + virtual bool InitializeTypeInfo(iFCO* pFCO) ; +}; + +#endif //__FSDATASOURCEITER_H + diff --git a/src/fs/fsdatasourceiter_t.cpp b/src/fs/fsdatasourceiter_t.cpp new file mode 100644 index 0000000..398786d --- /dev/null +++ b/src/fs/fsdatasourceiter_t.cpp @@ -0,0 +1,118 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fsdatasourceiter_t +#include "stdfs.h" +#include "fsdatasourceiter.h" +#include "core/fsservices.h" +#include "core/debug.h" +#include "test/test.h" +#include "fco/fco.h" + +/* +static void PrintDb( cHierDatabase::iterator iter, cDebug d, bool bFirst = true ) +{ + if( ! bFirst ) + { + iter.Descend(); + } + d.TraceDebug( "-- Processing directory %s\n", iter.GetCwd().c_str() ); + + for( iter.SeekBegin(); ! iter.Done(); iter.Next() ) + { + d.TraceDebug( "Processing entry %s\n", iter.GetName().c_str() ); + if( iter.CanDescend() ) + { + d.TraceDebug( ">>Descending...\n" ); + PrintDb(iter, d, false); + } + } + + d.TraceDebug( "-- Done Processing directory %s\n", iter.GetCwd().c_str() ); +} +*/ + +static void PrintIter( cFSDataSourceIter iter, cDebug& d ) +{ + // + //debug stuff + // + + if( ! iter.CanDescend() ) + { + d.TraceError( "Iterator cannot descend; returning!\n"); + return; + } + iter.Descend(); + iter.TraceContents(); + + for( iter.SeekBegin(); ! iter.Done(); iter.Next() ) + { + iFCO* pFCO = iter.CreateFCO(); + if( pFCO ) + { + pFCO->TraceContents(); + pFCO->Release(); + } + else + { + d.TraceError( "*** Create of FCO failed!\n"); + } + if( iter.CanDescend() ) + { + d.TraceDebug( ">>Descending...\n" ); + PrintIter(iter, d); + } + } +} + + +void TestFSDataSourceIter() +{ + cFSDataSourceIter iter; + cDebug d("TestFSDataSourceIter"); + try + { + // go to my temp directory and iterate over everything! + iter.SeekToFCO( cFCOName(_T("d:/test")) ); + // + // print out everything below the iterator + // + PrintIter( iter, d ); + } + catch( eError& e ) + { + d.TraceError( "*** Caught exception %d %s\n", e.GetID(), e.GetMsg() ); + TEST( false ); + } +} + + diff --git a/src/fs/fserrors.cpp b/src/fs/fserrors.cpp new file mode 100644 index 0000000..21a1125 --- /dev/null +++ b/src/fs/fserrors.cpp @@ -0,0 +1,53 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fserrors.cpp +// +// Registers all error strings in the fs package +// + +#include "stdfs.h" +#include "fserrors.h" +#include "fspropcalc.h" +#include "fsdatasourceiter.h" +#include "core/errortable.h" + + +TSS_BEGIN_ERROR_REGISTRATION( fs ) + +TSS_REGISTER_ERROR( eFSPropCalc(), _T("NTFS property calculation error.") ) +//TSS_REGISTER_ERROR( eFSPropCalcResetAccessTime(), _T("Could not reset access time for file.") ) +TSS_REGISTER_ERROR( eFSDataSourceIter(), _T("Data source iterator error.") ) +TSS_REGISTER_ERROR( eFSDataSourceIterReadDir(), _T("Could not access directory contents.") ) + + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/fs/fserrors.h b/src/fs/fserrors.h new file mode 100644 index 0000000..2369419 --- /dev/null +++ b/src/fs/fserrors.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: fserrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __FSERRORS_H +#define __FSERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( fs ) + +#endif//__FSERRORS_H + diff --git a/src/fs/fsfactory.cpp b/src/fs/fsfactory.cpp new file mode 100644 index 0000000..297faad --- /dev/null +++ b/src/fs/fsfactory.cpp @@ -0,0 +1,131 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsfactory.cpp + +#include "stdfs.h" + +#include "fsfactory.h" +#include "fspropcalc.h" +#include "fco/fcospecimpl.h" +#include "fspropdisplayer.h" +#include "fsobject.h" +#include "fsparserutil.h" +#include "fsdatasourceiter.h" +#include "fco/fconameinfo.h" +#include "fsnametranslator.h" + +//----------------------------------------------------------------------------- +// cUnixFCONameInfo +//----------------------------------------------------------------------------- +class cUnixNameInfo : public iFCONameInfo +{ +public: + virtual bool IsCaseSensitive() const + { + return true; + } + + virtual TCHAR GetDelimitingChar() const + { + return _T('/'); + } +}; + + +iFCOPropCalc* cFSFactory::CreatePropCalc() const +{ + return new cFSPropCalc(); +} + +iFCOSpec* cFSFactory::CreateSpec(const TSTRING& name, iFCOSpecHelper* pHelper) const +{ + return new cFCOSpecImpl(name, NULL, pHelper); +} + +iFCOPropDisplayer* cFSFactory::CreatePropDisplayer() const +{ + return new cFSPropDisplayer(); +} + +iSerRefCountObj::CreateFunc cFSFactory::GetCreateFunc() const +{ + return cFSObject::Create; +} + +iParserGenreUtil* cFSFactory::CreateParserGenreUtil() const +{ + return new cFSParserUtil(); +} + +iFCODataSourceIter* cFSFactory::CreateDataSourceIter() const +{ + return new cFSDataSourceIter(); +} + + +iFCONameInfo* cFSFactory::GetNameInfo() const +{ + static cUnixNameInfo gUnixNameInfo; + return &gUnixNameInfo; +} + +cFCOPropVector cFSFactory::GetLooseDirMask() const +{ + static cFCOPropVector vec; + static bool bInit = false; + + if( ! bInit ) + { + vec.AddItem( cFSPropSet::PROP_SIZE ); + vec.AddItem( cFSPropSet::PROP_NLINK ); + vec.AddItem( cFSPropSet::PROP_ATIME ); + vec.AddItem( cFSPropSet::PROP_CTIME ); + vec.AddItem( cFSPropSet::PROP_MTIME ); + vec.AddItem( cFSPropSet::PROP_BLOCKS ); + vec.AddItem( cFSPropSet::PROP_GROWING_FILE ); + vec.AddItem( cFSPropSet::PROP_CRC32 ); + vec.AddItem( cFSPropSet::PROP_MD5 ); + vec.AddItem( cFSPropSet::PROP_SHA ); + vec.AddItem( cFSPropSet::PROP_HAVAL ); + + bInit = true; + } + + return vec; +} + +iFCONameTranslator* cFSFactory::GetNameTranslator() const +{ + static cFSNameTranslator gFSNameTranslator; + return (&gFSNameTranslator); +} diff --git a/src/fs/fsfactory.h b/src/fs/fsfactory.h new file mode 100644 index 0000000..0d49077 --- /dev/null +++ b/src/fs/fsfactory.h @@ -0,0 +1,62 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsfactory.h +// +// cFSFactory -- an implementation of iTWFactory that creates file system objects +#ifndef __FSFACTORY_H +#define __FSFACTORY_H + +#ifndef __TWFACTORY_H +#include "fco/twfactory.h" +#endif + +class cFSFactory : public iTWFactory +{ +public: + cFSFactory() {} + virtual ~cFSFactory() {} + + virtual iFCOPropCalc* CreatePropCalc() const; + virtual iFCOSpec* CreateSpec(const TSTRING& name, iFCOSpecHelper* pHelper) const; + virtual iFCOPropDisplayer* CreatePropDisplayer() const; + virtual iParserGenreUtil* CreateParserGenreUtil() const; + virtual iSerRefCountObj::CreateFunc GetCreateFunc() const; + virtual iFCODataSourceIter* CreateDataSourceIter() const ; + virtual iFCONameInfo* GetNameInfo() const ; + virtual cFCOPropVector GetLooseDirMask() const ; + virtual iFCONameTranslator* GetNameTranslator() const; + +}; + +#endif //__FSFACTORY_H + diff --git a/src/fs/fsnametranslator.cpp b/src/fs/fsnametranslator.cpp new file mode 100644 index 0000000..a11434e --- /dev/null +++ b/src/fs/fsnametranslator.cpp @@ -0,0 +1,130 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsnametranslator.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfs.h" + +#include "fsnametranslator.h" +#include "fco/fconame.h" +#include "util/stringencoder.h" +#include "core/displayencoder.h" +#include "core/debug.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + + +/////////////////////////////////////////////////////////////////////////////// +// ToStringRaw +/////////////////////////////////////////////////////////////////////////////// +TSTRING cFSNameTranslator::ToStringRaw( const cFCOName& name ) const +{ + return name.AsString(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ToStringAPI +/////////////////////////////////////////////////////////////////////////////// +TSTRING cFSNameTranslator::ToStringAPI( const cFCOName& name ) const +{ + ASSERT( name.GetDelimiter() == _T('/') ); + + return name.AsString(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ToStringDisplay +/////////////////////////////////////////////////////////////////////////////// +TSTRING cFSNameTranslator::ToStringDisplay( const cFCOName& name, bool bUnique ) const +{ + TSTRING strRet; + + if( bUnique ) + { + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + TSTRING strUnencoded = name.AsString(); + e.Encode( strUnencoded ); + const TCHAR dq = _T('\"'); + + strRet += dq; + strRet += strUnencoded; + strRet += dq; + } + else + { + cDisplayEncoder e( cDisplayEncoder::NON_ROUNDTRIP ); // cDisplayEncoder + strRet = name.AsString(); + e.Encode( strRet ); + } + + return strRet; +} + +/////////////////////////////////////////////////////////////////////////////// +// DisplayStringToFCOName +/////////////////////////////////////////////////////////////////////////////// +bool cFSNameTranslator::DisplayStringToFCOName( const TSTRING& strC, cFCOName& name ) const +{ + TSTRING str = strC; + const TCHAR dq = _T('\"'); + + // do a little error checking. must have at least '""' + if( str.size() < 1 ) + return false; + if( dq != str[0] ) + return false; + if( dq != str[str.size() - 1] ) + return false; + + // get rid of beginning and trailing quote + str = str.substr( 1, str.size() - 2 ); + + // + // undo funky wide char encoding + // + cDisplayEncoder e( cDisplayEncoder::ROUNDTRIP ); + if( ! e.Decode( str ) ) + return false; + + // give to cFCOName + name = str; + + return true; +} + diff --git a/src/fs/fsnametranslator.h b/src/fs/fsnametranslator.h new file mode 100644 index 0000000..2fce030 --- /dev/null +++ b/src/fs/fsnametranslator.h @@ -0,0 +1,64 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsnametranslator.h +// + +#ifndef __FSNAMETRANSLATOR_H +#define __FSNAMETRANSLATOR_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __FCONAMETRANSLATOR_H +#include "fco/fconametranslator.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +class cFSNameTranslator : public iFCONameTranslator +{ +public: + // + // basic functionality + // + virtual TSTRING ToStringRaw( const cFCOName& name ) const; + virtual TSTRING ToStringAPI( const cFCOName& name ) const; + virtual TSTRING ToStringDisplay( const cFCOName& name, bool bUnique = false ) const; + virtual bool DisplayStringToFCOName( const TSTRING& str, cFCOName& name ) const; +}; + +#endif //__FSNAMETRANSLATOR_H + diff --git a/src/fs/fsobject.cpp b/src/fs/fsobject.cpp new file mode 100644 index 0000000..360665a --- /dev/null +++ b/src/fs/fsobject.cpp @@ -0,0 +1,199 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsobject.cpp + +#include "stdfs.h" + +#include "fco/fconame.h" +#include "fsobject.h" +#include "fsvisitor.h" +#include "core/serializer.h" +#include "core/error.h" +#include "core/errorutil.h" + +//uncomment to allocate fsobjects from a pool +//cObjectPoolBase cFSObject::msAllocator(sizeof(cFSObject), 1000); + +// FCO Type information... +IMPLEMENT_SERREFCOUNT(cFSObject, _T("FSObject"), 0, 1) + +// Debug stuff +#ifdef _DEBUG +static int gNumFSObjectCreate = 0; +static int gNumFSObjectDestroy = 0; + +void cFSObject::TraceStats() +{ + cDebug d("cFSObject::TraceStats"); + + d.TraceDebug("cFSObject Stats:\n\tNum Created:\t%d\n\tNum Destroyed:\t%d\n", + gNumFSObjectCreate, gNumFSObjectDestroy); +} + + +class cFSNameStatPrinter +{ +public: + ~cFSNameStatPrinter() + { + cDebug d("cFSNameStatPrinter"); + d.TraceDebug("*** Num fs objects created: %d Num destroyed: %d ***\n", gNumFSObjectCreate, gNumFSObjectDestroy ); + } + +} gFSNameStatPrinter; + +#endif //_DEBUG + + +cFSObject::cFSObject(const cFCOName& name) : + mName(name) +{ +#ifdef _DEBUG + gNumFSObjectCreate++; +#endif +} + +cFSObject::cFSObject() : + mName(_T("undefined")) +{ +#ifdef _DEBUG + gNumFSObjectCreate++; +#endif +} + +cFSObject::~cFSObject() +{ +#ifdef _DEBUG + gNumFSObjectDestroy++; +#endif +} + +const cFCOName& cFSObject::GetName() const +{ + return mName; +} + +void cFSObject::SetName(const cFCOName& name) +{ + mName = name; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetCaps +/////////////////////////////////////////////////////////////////////////////// +uint32 cFSObject::GetCaps() const +{ + uint32 cap = mName.GetSize() > 1 ? CAP_CAN_HAVE_PARENT : 0; + + ASSERT( GetFSPropSet().GetValidVector().ContainsItem( cFSPropSet::PROP_FILETYPE ) ); + if( GetFSPropSet().GetFileType() == cFSPropSet::FT_DIR ) + { + cap |= CAP_CAN_HAVE_CHILDREN; + } + + return cap; +} + + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFSObject::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFSObject::TraceContents"); + + d.Trace(dl, _T("%s\n"), GetName().AsString().c_str()); + // trace the property set's stats + GetPropSet()->TraceContents(dl); +} + +/////////////////////////////////////////////////////////////////////////////// +// retrieving the property set and children... +/////////////////////////////////////////////////////////////////////////////// +const iFCOPropSet* cFSObject::GetPropSet() const +{ + return &mPropSet; +} + +iFCOPropSet* cFSObject::GetPropSet() +{ + return &mPropSet; +} + +/////////////////////////////////////////////////////////////////////////////// +// Clone +/////////////////////////////////////////////////////////////////////////////// +iFCO* cFSObject::Clone() const +{ + cFSObject* pNew = new cFSObject(GetName()); + // copy all the properties... + pNew->GetFSPropSet() = GetFSPropSet(); + // note that we don't get the children... + return pNew; +} + +/////////////////////////////////////////////////////////////////////////////// +// Visitor Interface +/////////////////////////////////////////////////////////////////////////////// +void cFSObject::AcceptVisitor(iFCOVisitor* pVisitor) +{ + // first, make sure this is the right type... + ASSERT(pVisitor->GetType() == iFSVisitor::mType); + iFSVisitor* pfsv = static_cast(pVisitor); + pfsv->VisitFSObject(*this); +} + + +void cFSObject::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("File System Object"))); + + + pSerializer->ReadObject(&mName); + pSerializer->ReadObject(&mPropSet); +} + +void cFSObject::Write(iSerializer* pSerializer) const +{ + + pSerializer->WriteObject(&mName); + pSerializer->WriteObject(&mPropSet); +} + + + diff --git a/src/fs/fsobject.h b/src/fs/fsobject.h new file mode 100644 index 0000000..6c5bb16 --- /dev/null +++ b/src/fs/fsobject.h @@ -0,0 +1,116 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsobject.h -- FCO-derived classes for file systems +// +// cFSObject -- base class for files and directories +// +#ifndef __FSOBJECT_H +#define __FSOBJECT_H + +#ifndef __FCO_H +#include "fco/fco.h" +#endif + +#ifndef __FSPROPSET_H +#include "fspropset.h" +#endif + +#ifndef __FCOSETIMPL_H +#include "fco/fcosetimpl.h" +#endif + +#ifndef __FCONAME_H +#include "fco/fconame.h" +#endif + +/////////////////////////////////////////////////////////////////// +// cFSObject -- base class for files and directory FCOs +class cFSObject : public iFCO +{ + DECLARE_SERREFCOUNT() + +public: + cFSObject(const cFCOName& name); + + virtual void SetName(const cFCOName& name) ; + virtual const cFCOName& GetName() const ; + + virtual const iFCOPropSet* GetPropSet() const ; + virtual iFCOPropSet* GetPropSet() ; + virtual uint32 GetCaps() const ; + + virtual iFCO* Clone() const ; + virtual void AcceptVisitor(iFCOVisitor* pVisitor) ; + + const cFSPropSet& GetFSPropSet() const; + cFSPropSet& GetFSPropSet(); + // returns a reference to the FS property set + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + virtual void TraceContents(int dl = -1) const; + +#ifdef _DEBUG + static void TraceStats() ; + // this TRACEs statistics on FSObject usage that is pertinent to performance or mem leakage + // concerns. +#endif + + cFSObject(); + virtual ~cFSObject(); + // only destroy by calling Release(); Also prevents creation on the + // stack. + +private: + cFSPropSet mPropSet; + cFCOName mName; +}; + +////////////////////////////////////////////////////// +// inline implementation +////////////////////////////////////////////////////// +inline const cFSPropSet& cFSObject::GetFSPropSet() const +{ + return mPropSet; +} + +inline cFSPropSet& cFSObject::GetFSPropSet() +{ + return mPropSet; +} + + +#endif + diff --git a/src/fs/fsobject_t.cpp b/src/fs/fsobject_t.cpp new file mode 100644 index 0000000..8d4e4a1 --- /dev/null +++ b/src/fs/fsobject_t.cpp @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fsobject_t -- the file system object test driver +#include "stdfs.h" +#include "fsobject.h" + +void TestFSObject() +{ + return; +} diff --git a/src/fs/fsparserutil.cpp b/src/fs/fsparserutil.cpp new file mode 100644 index 0000000..0c08e50 --- /dev/null +++ b/src/fs/fsparserutil.cpp @@ -0,0 +1,195 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsparserutil.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdfs.h" + +#include "fsparserutil.h" +#include "core/fsservices.h" +#include "fspropset.h" +#include "fsstrings.h" +#include "fco/fcopropvector.h" +#include "fco/fconame.h" +#include "fco/fcostrings.h" + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + +bool cFSParserUtil::MapStringToProperty( const TSTRING& str, int& propIndex ) const +{ + bool fMappedChar = true; // assume we'll recognize this char + // and set false if we don't + + // for short names + if( str.length() == 1 ) + { + switch( str[0] ) + { + case 'p': propIndex = cFSPropSet::PROP_MODE; break; + case 'i': propIndex = cFSPropSet::PROP_INODE; break; + case 'n': propIndex = cFSPropSet::PROP_NLINK; break; + case 'u': propIndex = cFSPropSet::PROP_UID; break; + case 'g': propIndex = cFSPropSet::PROP_GID; break; + case 's': propIndex = cFSPropSet::PROP_SIZE; break; + case 't': propIndex = cFSPropSet::PROP_FILETYPE;break; + case 'd': propIndex = cFSPropSet::PROP_DEV; break; + case 'r': propIndex = cFSPropSet::PROP_RDEV; break; + case 'b': propIndex = cFSPropSet::PROP_BLOCKS; break; + case 'a': propIndex = cFSPropSet::PROP_ATIME; break; + case 'm': propIndex = cFSPropSet::PROP_MTIME; break; + case 'c': propIndex = cFSPropSet::PROP_CTIME; break; + case 'C': propIndex = cFSPropSet::PROP_CRC32; break; + case 'M': propIndex = cFSPropSet::PROP_MD5; break; + case 'S': propIndex = cFSPropSet::PROP_SHA; break; + case 'H': propIndex = cFSPropSet::PROP_HAVAL; break; + case 'l': propIndex = cFSPropSet::PROP_GROWING_FILE; break; + default: fMappedChar = false; break; + } + } + else + { + if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_MODE ) ) ) + propIndex = cFSPropSet::PROP_MODE; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_INODE ) ) ) + propIndex = cFSPropSet::PROP_INODE; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_UID ) ) ) + propIndex = cFSPropSet::PROP_UID; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_GID ) ) ) + propIndex = cFSPropSet::PROP_GID; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_SIZE ) ) ) + propIndex = cFSPropSet::PROP_SIZE; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_FILETYPE ) ) ) + propIndex = cFSPropSet::PROP_FILETYPE; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_DEV ) ) ) + propIndex = cFSPropSet::PROP_DEV; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_RDEV ) ) ) + propIndex = cFSPropSet::PROP_RDEV; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_BLOCKS ) ) ) + propIndex = cFSPropSet::PROP_BLOCKS; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_ATIME ) ) ) + propIndex = cFSPropSet::PROP_ATIME; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_MTIME ) ) ) + propIndex = cFSPropSet::PROP_MTIME; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_CTIME ) ) ) + propIndex = cFSPropSet::PROP_CTIME; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_CRC32 ) ) ) + propIndex = cFSPropSet::PROP_CRC32; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_MD5 ) ) ) + propIndex = cFSPropSet::PROP_MD5; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_SHA ) ) ) + propIndex = cFSPropSet::PROP_SHA; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_HAVAL ) ) ) + propIndex = cFSPropSet::PROP_HAVAL; + else if( 0 == str.compare( TSS_GetString( cFS, fs::STR_PARSER_PROP_GROWING_FILE ) ) ) + propIndex = cFSPropSet::PROP_GROWING_FILE; + else + fMappedChar = false; + } + + return( fMappedChar ); +} + +void cFSParserUtil::AddSubTypeProps( cFCOPropVector& v ) const +{ + v.AddItemAndGrow( cFSPropSet::PROP_FILETYPE ); +} + +void cFSParserUtil::InterpretFCOName( const std::list& l, cFCOName& nameOut ) const +{ + TSTRING strT; + for( std::list::const_iterator i = l.begin(); i != l.end(); i++ ) + strT += *i; + + // let cFCOName handle interpretation + nameOut = strT; +} + +bool cFSParserUtil::EnumPredefinedVariables( int index, TSTRING& sName, TSTRING& sValue ) const +{ + switch( index ) + { + case 0: + sName = TSS_GetString( cFS, fs::STR_PARSER_READONLY ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_READONLY_VAL ); + return true; + case 1: + sName = TSS_GetString( cFS, fs::STR_PARSER_DYNAMIC ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_DYNAMIC_VAL ); + return true; + case 2: + sName = TSS_GetString( cFS, fs::STR_PARSER_GROWING ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_GROWING_VAL ); + return true; + case 3: + sName = TSS_GetString( cFS, fs::STR_PARSER_IGNOREALL ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_IGNOREALL_VAL ); + return true; + case 4: + sName = TSS_GetString( cFS, fs::STR_PARSER_IGNORENONE ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_IGNORENONE_VAL ); + return true; + case 5: + sName = TSS_GetString( cFS, fs::STR_PARSER_DEVICE ); + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_DEVICE_VAL ); + return true; + case 6: + sName = TSS_GetString( cFS, fs::STR_PARSER_HOSTNAME ); + try + { + iFSServices::GetInstance()->GetMachineName( sValue); + if (sValue.empty()) + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_HOSTNAME_VAL ); + } + catch( eFSServices& ) + { + sValue = TSS_GetString( cFS, fs::STR_FS_PARSER_HOSTNAME_VAL ); + } + return true; + default: + return false; + } + + ASSERT( false ); // unreachable code +} + +bool cFSParserUtil::IsAbsolutePath( const TSTRING& strPath ) const +{ + // IF there's a first character AND it is ( '/' OR '\\' ), THEN it's absolute + return( strPath.size() > 0 && ( _T('/') == strPath[0] || _T('\\') == strPath[0] ) ); +} diff --git a/src/fs/fsparserutil.h b/src/fs/fsparserutil.h new file mode 100644 index 0000000..b0e1b7c --- /dev/null +++ b/src/fs/fsparserutil.h @@ -0,0 +1,83 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fsparserutil.h +// +// + +#ifndef __FSPARSERUTIL_H +#define __FSPARSERUTIL_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __PARSERGENREUTIL_H +#include "fco/parsergenreutil.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +class cFSParserUtil : public iParserGenreUtil +{ +public: + virtual bool MapStringToProperty( const TSTRING& str, int& propIndex ) const; + // maps the given string to an index into a property vector for the genre + virtual void AddSubTypeProps( cFCOPropVector& v ) const; + // add props that define object sub-type in genre + virtual void InterpretFCOName( const std::list& l, cFCOName& nameOut ) const; // throw( eParserGenreUtil ) + // given the input string list from the policy file, creates the cFCOName + virtual bool EnumPredefinedVariables( int index, TSTRING& sName, TSTRING& sValue ) const; + // set index to 0 before first call, then increment for each subsequent call. + // returns true if more var/val pairs + virtual bool IsAbsolutePath( const TSTRING& strPath ) const; + // returns true if the path is an absolute path, and false if it's relative. + virtual bool HasSingleLetterProps() const; + // returns true if this genre uses single-letter to represent object properties + // in the policy language and the command line. If it returns false, the genre + // uses &-separated words. +}; + + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + +inline bool cFSParserUtil::HasSingleLetterProps() const +{ + return true; +} + +#endif //__FSPARSERUTIL_H + diff --git a/src/fs/fspropcalc.cpp b/src/fs/fspropcalc.cpp new file mode 100644 index 0000000..72dac00 --- /dev/null +++ b/src/fs/fspropcalc.cpp @@ -0,0 +1,406 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropcalc.cpp + +#include "stdfs.h" +#include "core/debug.h" +#include "core/errorbucket.h" +#include "core/fsservices.h" +#include "core/errorbucket.h" +#include "fco/fconame.h" +#include "fco/fconametranslator.h" +#include "fco/twfactory.h" +#include "core/archive.h" + +#include "fspropcalc.h" +#include "fsobject.h" + +#if IS_UNIX +#include +#endif + + +cFSPropCalc::cFSPropCalc() : + mCollAction(iFCOPropCalc::PROP_LEAVE), mCalcFlags(0), mpErrorBucket(0) +{ +} + +cFSPropCalc::~cFSPropCalc() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// NeedsStat -- returns true if any properties are in the vector that require +// a stat() call +/////////////////////////////////////////////////////////////////////////////// +static bool NeedsStat(const cFCOPropVector& v) +{ + return ( v.ContainsItem(cFSPropSet::PROP_DEV) || + v.ContainsItem(cFSPropSet::PROP_RDEV) || + v.ContainsItem(cFSPropSet::PROP_INODE) || + v.ContainsItem(cFSPropSet::PROP_MODE) || + v.ContainsItem(cFSPropSet::PROP_NLINK) || + v.ContainsItem(cFSPropSet::PROP_UID) || + v.ContainsItem(cFSPropSet::PROP_GID) || + v.ContainsItem(cFSPropSet::PROP_SIZE) || + v.ContainsItem(cFSPropSet::PROP_ATIME) || + v.ContainsItem(cFSPropSet::PROP_MTIME) || + v.ContainsItem(cFSPropSet::PROP_CTIME) || + v.ContainsItem(cFSPropSet::PROP_BLOCK_SIZE) || + v.ContainsItem(cFSPropSet::PROP_BLOCKS) || + v.ContainsItem(cFSPropSet::PROP_FILETYPE) || + v.ContainsItem(cFSPropSet::PROP_GROWING_FILE) + ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSymLinkStr -- returns a string that represents what a symbolic link is +// pointing at. If this returns false, call iFSServices::GetErrnoString() +// to get the error message. +/////////////////////////////////////////////////////////////////////////////// + + +static bool GetSymLinkStr(const cFCOName& fileName, cArchive& arch) +{ +#if !IS_WIN32 +#ifdef _UNICODE +#error GetSymLinkStr in fspropcalc.cpp is not unicode compliant +#else // ifdef _UNICODE + char buf[1024]; + int rtn = readlink( iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( fileName ).c_str(), + buf, 1024 ); + if(rtn == -1) + return false; + + // the return value is the number of characters written. + arch.WriteBlob(buf, rtn); + + return true; + +#endif // ifdef _UNICODE +#else // if !IS_WIN32 + return false; // TODO: find better way to do this -- just a place holder +#endif // if !IS_WIN32 +} + + +/////////////////////////////////////////////////////////////////////////////// +// VisitFSObject -- this is the workhorse method that actually fills out the +// passed in FSObject' properties +/////////////////////////////////////////////////////////////////////////////// +void cFSPropCalc::VisitFSObject(cFSObject& obj) +{ + cDebug d("cFSPropCalc::VisitFSObject"); + d.TraceDetail(_T("Visiting %s\n"), obj.GetName().AsString().c_str()); + + // if we are not in overwrite mode, we need to alter the + // properties we are calculating... + cFCOPropVector propsToCheck(mPropVector); + if(mCollAction == iFCOPropCalc::PROP_LEAVE) + { + cFCOPropVector inBoth = propsToCheck; + inBoth &= obj.GetPropSet()->GetValidVector(); + propsToCheck ^= inBoth; + } + +#ifdef _DEBUG + d.TraceDetail("----->Collision Action = %s\n", mCollAction == iFCOPropCalc::PROP_LEAVE ? "Leave" : "Replace"); + d.TraceDetail("----->Object's valid properties (a):\n"); + obj.GetPropSet()->GetValidVector().TraceContents(cDebug::D_DETAIL); + d.TraceDetail("----->Properties to calculate: (b)\n"); + mPropVector.TraceContents(cDebug::D_DETAIL); + d.TraceDetail("----->Properties to change in object ((a&b)^b for Leave or b for Replace):\n"); + propsToCheck.TraceContents(cDebug::D_DETAIL); +#endif //_DEBUG + + // only do the stat() if it is necessary + iFSServices* pFSServices = iFSServices::GetInstance(); + cFSStatArgs ss; + bool bDidStat = false; + TSTRING strName = iTWFactory::GetInstance()->GetNameTranslator()->ToStringAPI( obj.GetName() ); + + // get a reference to the fco's property set + cFSPropSet& propSet = obj.GetFSPropSet(); + + // + // just return if this object is invalid + // + if( propSet.GetFileType() == cFSPropSet::FT_INVALID ) + return; + + try + { + if( NeedsStat(propsToCheck) ) + { + d.TraceDetail("---Performing Stat()\n"); + pFSServices->Stat(strName, ss); + bDidStat = true; + } + } + catch(eFSServices& e) + { + d.TraceError("Error getting stat info for %s : %s\n", strName.c_str(), e.GetMsg().c_str()); + + // add this fco to the error set... + // it is assumed that the file name that the error is associated with is in the exception's + // GetMsg() + e.SetFatality( false ); + if(mpErrorBucket) + mpErrorBucket->AddError( e ); + return; + } + + // for now, I will only fill out the stat info indicated in the property vector, + // but in reality, there is no reason not to fill out everything, since we have the + // extra information for free! + if(bDidStat) + { + if(propsToCheck.ContainsItem(cFSPropSet::PROP_DEV)) + propSet.SetDev(ss.dev); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_RDEV)) + propSet.SetRDev(ss.rdev); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_INODE)) + propSet.SetInode(ss.ino); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MODE)) + propSet.SetMode(ss.mode); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_NLINK)) + propSet.SetNLink(ss.nlink); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_UID)) + propSet.SetUID(ss.uid); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_GID)) + propSet.SetGID(ss.gid); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_SIZE)) + propSet.SetSize(ss.size); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_ATIME)) + propSet.SetAccessTime(ss.atime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MTIME)) + propSet.SetModifyTime(ss.mtime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_CTIME)) + propSet.SetCreateTime(ss.ctime); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCK_SIZE)) + propSet.SetBlockSize(ss.blksize); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_BLOCKS)) + propSet.SetBlocks(ss.blocks); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_GROWING_FILE)) + propSet.SetGrowingFile(ss.size); + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_FILETYPE)) + { + // TODO -- It _really_ bites duplicating code here and in fsdatasource.cpp + // *** This _has_ to be remedied somehow! + // set the file type + switch(ss.mFileType) + { + case cFSStatArgs::TY_FILE: + propSet.SetFileType(cFSPropSet::FT_FILE); + break; + case cFSStatArgs::TY_DIR: + propSet.SetFileType(cFSPropSet::FT_DIR); + break; + case cFSStatArgs::TY_BLOCKDEV: + propSet.SetFileType(cFSPropSet::FT_BLOCKDEV); + break; + case cFSStatArgs::TY_CHARDEV: + propSet.SetFileType(cFSPropSet::FT_CHARDEV); + break; + case cFSStatArgs::TY_SYMLINK: + propSet.SetFileType(cFSPropSet::FT_SYMLINK); + break; + case cFSStatArgs::TY_FIFO: + propSet.SetFileType(cFSPropSet::FT_FIFO); + break; + case cFSStatArgs::TY_SOCK: + propSet.SetFileType(cFSPropSet::FT_SOCK); + break; + default: + // set it to invalid + propSet.SetFileType(cFSPropSet::FT_INVALID); + } + } + } + + // if the file type is not a regular file, we will + // not try to open the file for signature generation + ASSERT( propSet.GetValidVector().ContainsItem(cFSPropSet::PROP_FILETYPE) ); + if( propSet.GetFileType() == cFSPropSet::FT_FILE || propSet.GetFileType() == cFSPropSet::FT_SYMLINK ) + { + if( // if we need to open the file + propsToCheck.ContainsItem(cFSPropSet::PROP_CRC32) || + propsToCheck.ContainsItem(cFSPropSet::PROP_MD5) || + propsToCheck.ContainsItem(cFSPropSet::PROP_SHA) || + propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL) + ) + { + cFileArchive arch; + cMemoryArchive memArch; + cBidirArchive* pTheArch; + bool bInitSuccess = true; + if(propSet.GetFileType() == cFSPropSet::FT_SYMLINK) + { + pTheArch = &memArch; + if(! GetSymLinkStr(obj.GetName(), memArch)) + { + // add it to the bucket... + if(mpErrorBucket) + mpErrorBucket->AddError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL ) ); + bInitSuccess = false; + } + + } + else + { + pTheArch = &arch; + try + { + arch.OpenRead(strName.c_str()); + } + catch (eArchive&) + { + // add it to the bucket... + if(mpErrorBucket) + mpErrorBucket->AddError( eArchiveOpen( strName, iFSServices::GetInstance()->GetErrString(), eError::NON_FATAL ) ); + bInitSuccess = false; + } + } + + // + // if we have successfully initialized the archive + // + if (bInitSuccess) + { + cArchiveSigGen asg; + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_CRC32)) + { + propSet.SetDefinedCRC32(true); + asg.AddSig( propSet.GetCRC32() ); + } + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_MD5)) + { + propSet.SetDefinedMD5(true); + asg.AddSig( propSet.GetMD5() ); + } + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_SHA)) + { + propSet.SetDefinedSHA(true); + asg.AddSig( propSet.GetSHA() ); + } + + if(propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL)) + { + propSet.SetDefinedHAVAL(true); + asg.AddSig( propSet.GetHAVAL() ); + } + + // + // calculate the signatures + // + pTheArch->Seek( 0, cBidirArchive::BEGINNING ); + asg.CalculateSignatures( *pTheArch ); + arch.Close(); + } + } + } + else + { + // We can't calculate signatures, set them to undefined + if (propsToCheck.ContainsItem(cFSPropSet::PROP_CRC32)) + propSet.SetDefinedCRC32(false); + + if (propsToCheck.ContainsItem(cFSPropSet::PROP_MD5)) + propSet.SetDefinedMD5(false); + + if (propsToCheck.ContainsItem(cFSPropSet::PROP_SHA)) + propSet.SetDefinedSHA(false); + + if (propsToCheck.ContainsItem(cFSPropSet::PROP_HAVAL)) + propSet.SetDefinedHAVAL(false); + } +} + +void cFSPropCalc::SetPropVector(const cFCOPropVector& pv) +{ + mPropVector = pv; +} + +const cFCOPropVector& cFSPropCalc::GetPropVector() const +{ + return mPropVector; +} + +iFCOVisitor* cFSPropCalc::GetVisitor() +{ + return this; +} + +const iFCOVisitor* cFSPropCalc::GetVisitor() const +{ + return this; +} + +void cFSPropCalc::SetErrorBucket(cErrorBucket* pBucket) +{ + mpErrorBucket = pBucket; +} + +const cErrorBucket* cFSPropCalc::GetErrorBucket() const +{ + return mpErrorBucket; +} + +iFCOPropCalc::CollisionAction cFSPropCalc::GetCollisionAction() const +{ + return mCollAction; +} + +void cFSPropCalc::SetCollisionAction(CollisionAction a) +{ + ASSERT((a == iFCOPropCalc::PROP_OVERWRITE) || (a == PROP_LEAVE)); + mCollAction = a; +} + diff --git a/src/fs/fspropcalc.h b/src/fs/fspropcalc.h new file mode 100644 index 0000000..f99b942 --- /dev/null +++ b/src/fs/fspropcalc.h @@ -0,0 +1,98 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropcalc.h +// +// cFSPropCalc -- an FS fco visitor that "calculates" (or evaluates, populates, ...) +// the fco's properties +#ifndef __FSPROPCALC_H +#define __FSPROPCALC_H + +#ifndef __FCOPROPCALC_H +#include "fco/fcopropcalc.h" +#endif +#ifndef __FSVISITOR_H +#include "fsvisitor.h" +#endif +#ifndef __FCOPROPVECTOR_H +#include "fco/fcopropvector.h" +#endif + +TSS_EXCEPTION( eFSPropCalc, eError ) +//TSS_EXCEPTION( eFSPropCalcResetAccessTime, eFSPropCalc ) // this was never used + +class cFSPropCalc : public iFCOPropCalc, public iFSVisitor +{ +public: + cFSPropCalc(); + virtual ~cFSPropCalc(); + + // from iFSVisitor + virtual void VisitFSObject(cFSObject& obj); + + // from iFCOPropCalc + virtual void SetPropVector(const cFCOPropVector& pv); + virtual const cFCOPropVector& GetPropVector() const; + virtual iFCOVisitor* GetVisitor(); + virtual const iFCOVisitor* GetVisitor() const; + + virtual void SetErrorBucket(cErrorBucket* pBucket) ; + virtual const cErrorBucket* GetErrorBucket() const ; + + virtual CollisionAction GetCollisionAction() const; + virtual void SetCollisionAction(CollisionAction a); + + virtual int GetCalcFlags() const; + virtual void SetCalcFlags( int i ); +private: + cFSPropCalc( const cFSPropCalc& ); + void operator =( const cFSPropCalc& ); + + cFCOPropVector mPropVector; + iFCOPropCalc::CollisionAction mCollAction; + int mCalcFlags; + cErrorBucket* mpErrorBucket; +}; + +inline int cFSPropCalc::GetCalcFlags() const +{ + return mCalcFlags; +} + +inline void cFSPropCalc::SetCalcFlags( int i ) +{ + mCalcFlags = i; +} + + +#endif //__FSPROPCALC_H + diff --git a/src/fs/fspropcalc_t.cpp b/src/fs/fspropcalc_t.cpp new file mode 100644 index 0000000..cdb1dc5 --- /dev/null +++ b/src/fs/fspropcalc_t.cpp @@ -0,0 +1,131 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fspropcalc_t.cpp -- the fs property calculator test driver +#include "stdfs.h" +#include "fspropcalc.h" +#include "core/debug.h" +#include "fco/fcopropset.h" +#include "fspropset.h" +#include "test/test.h" +#include "fco/fco.h" + +/////////////////////////////////////////////////////////////////////////////// +// PrintProps -- prints out all the valid property names and values as pairs... +/////////////////////////////////////////////////////////////////////////////// +/* +static void PrintProps(const iFCO* pFCO) +{ + cDebug d("PrintProps"); + const iFCOPropSet* pSet = pFCO->GetPropSet(); + const cFCOPropVector& v = pSet->GetValidVector(); + + for(int i=0; iGetNumProps(); i++) + { + if(v.ContainsItem(i)) + { + d.TraceDebug("[%d] %s\t%s\n", i, pSet->GetPropName(i), pSet->GetPropAt(i)->AsString().c_str()); + } + } +} +*/ + + +void TestFSPropCalc() +{ +#pragma message( __FILE__ "(1) : TODO - implement this test file") +#if 0 + cDebug d("TestFSPropCalc"); + cFSDataSource ds; + + iFSServices* pFSServices = iFSServices::GetInstance(); + bool bCaseSensitive = pFSServices->IsCaseSensitive(); + + // oh boy! I finally get to test property calculation! + d.TraceDebug("Creating FCO c:\\temp\\foo.bin\n"); + + cFileArchive arch; + int ret; + ret = arch.OpenReadWrite(TEMP_DIR _T("/foo.bin"), true); + TEST(ret); + arch.WriteBlob("\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0", 10); + arch.Close(); + + // get the fco but none of its children... + iFCO* pFCO = ds.CreateFCO(cFCOName(TEMP_DIR _T("/foo.bin")), 0); + ASSERT(pFCO); + + // create the calculator and set some properties to calculate... + cFSPropCalc propCalc; + cFCOPropVector v(pFCO->GetPropSet()->GetValidVector().GetSize()); + v.AddItem(cFSPropSet::PROP_DEV); + v.AddItem(cFSPropSet::PROP_CTIME); + v.AddItem(cFSPropSet::PROP_SIZE); + v.AddItem(cFSPropSet::PROP_BLOCKS); + v.AddItem(cFSPropSet::PROP_CRC32); + v.AddItem(cFSPropSet::PROP_MD5); + propCalc.SetPropVector(v); + + // finally, do the calculation + pFCO->AcceptVisitor(&propCalc); + + // see what properties were evaluated... + PrintProps(pFCO); + + d.TraceDebug("CRC32 should be \"2ARm2G\"\n"); + d.TraceDebug("MD5 should be \"1.Oyjj1dbom.DF2KktvtQe\"\n"); + + // if we do it with "Leave", then nothing should change... + d.TraceDebug("Changing collision action to Leave; the following run should _not_ call Stat()\n"); + propCalc.SetCollisionAction(iFCOPropCalc::PROP_LEAVE); + pFCO->AcceptVisitor(&propCalc); + + + // test only calculating unevaluated props... + d.TraceDebug("invalidating PROP_MD5 in fco, and changing the file. \n\tAll should remain the same except md5.\n"); + ret = arch.OpenReadWrite(TEMP_DIR _T("/foo.bin"), true); + TEST(ret); + arch.WriteString(_T("Bark Bark Bark\n")); + arch.Close(); + + // do the calculation + pFCO->GetPropSet()->InvalidateProp(cFSPropSet::PROP_MD5); + pFCO->AcceptVisitor(&propCalc); + PrintProps(pFCO); + + + // TODO -- is there any way to test the error queue in the prop calc? + + // release the fco + pFCO->Release(); +#endif + return; +} diff --git a/src/fs/fspropdisplayer.cpp b/src/fs/fspropdisplayer.cpp new file mode 100644 index 0000000..4e09e65 --- /dev/null +++ b/src/fs/fspropdisplayer.cpp @@ -0,0 +1,512 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropdisplayer.cpp +// + +#include "stdfs.h" + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "fspropdisplayer.h" +#include "fspropset.h" +#include "core/fsservices.h" +#include "core/serializer.h" +#include "core/timeconvert.h" +#include "fco/fconame.h" +#include "fco/fco.h" +#include "core/twlocale.h" +#include "core/displayencoder.h" +#include "fco/fcoundefprop.h" +#include "core/errorutil.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +#if !IS_AIX +// For some stupid linker reason, this object does not get constructed under +// AIX. The cheap fix is to move this call to fs.cpp. +IMPLEMENT_TYPEDSERIALIZABLE( cFSPropDisplayer, _T("FSPropDisplayer"), 0, 1 ); +#endif + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +//========================================================================= +// METHOD CODE +//========================================================================= + +cFSPropDisplayer::cFSPropDisplayer() + : mbLazy( false ) +{ + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_UID ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_GID ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_ATIME ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_MTIME ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_CTIME ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_MODE ); + + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_BLOCK_SIZE ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_BLOCKS ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_SIZE ); + mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_NLINK ); +} + +iFCOPropDisplayer* cFSPropDisplayer::Clone() const +{ + iFCOPropDisplayer* pNew = new cFSPropDisplayer; + pNew->Merge( this ); + return pNew; +} + +bool cFSPropDisplayer::IsMultiLineProp( int propID ) const +{ + // no FS props are multiline + return false; +} + +cFSPropDisplayer::~cFSPropDisplayer() +{ + cDebug d("~cFSPropDisplayer"); + d.TraceNever( "Destructor called on object %x\n", (ptr_size_type)this); +} + +const cFCOPropVector& cFSPropDisplayer::GetPropsConverted() const +{ + return mpvPropsWeDisplay; +} + +void cFSPropDisplayer::SetLazy( const bool bLazy /* = true */ ) +{ + mbLazy = bLazy; +} + +bool cFSPropDisplayer::GetLazy() const +{ + return mbLazy; +} + +// adds all prop display info from rhs to this +void cFSPropDisplayer::Merge( const iFCOPropDisplayer* const ppd ) +{ + ASSERT( ppd != 0); + + // should only merge two prop displayers of the same type + if( ppd->GetType() != this->GetType() ) + ASSERT( false ); + + const cFSPropDisplayer* const pfspd = static_cast( ppd ); + + // merge propvectors + mpvPropsWeDisplay |= pfspd->GetPropsConverted(); + + + // merge mapping info + for( INT64_TO_STRING_MAP::const_iterator iterUID = pfspd->uidToUsername.begin(); + iterUID != pfspd->uidToUsername.end(); + iterUID++ + ) + { + AddUsernameMapping( iterUID->first, iterUID->second ); + } + + for( INT64_TO_STRING_MAP::const_iterator iterGID = pfspd->gidToGroupname.begin(); + iterGID != pfspd->gidToGroupname.end(); + iterGID++ + ) + { + AddGroupnameMapping( iterGID->first, iterGID->second ); + } + + // keep lazy flag the same +} + + +TSTRING& cFSPropDisplayer::GetDetailsHeader( TSTRING& strBuf, int iMargin ) const +{ + static cFSPropSet set; + TOSTRINGSTREAM sstr; + + sstr << std::left; + sstr << _T(" ") << std::setw( PROP_MODE_WIDTH ) << set.GetPropName( cFSPropSet::PROP_MODE ); + sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH ) << set.GetPropName( cFSPropSet::PROP_UID ); + sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH ) << set.GetPropName( cFSPropSet::PROP_SIZE ); + sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH ) << set.GetPropName( cFSPropSet::PROP_MTIME ); + sstr << _T("\n"); + for( int i = 0; i < iMargin; i++ ) + sstr << _T(" "); + sstr << _T(" ") << std::setw( PROP_MODE_WIDTH ) << _T("------"); + sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH ) << _T("----------"); + sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH ) << _T("----------"); + sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH ) << _T("----------"); + + strBuf = sstr.str(); + return strBuf; +} + + +//////////////////////////////////////////////////////////////////////// +// Function name : cFSPropDisplayer::GetDetails +// Description : takes a TSTRING and fills it with an "ls -l" representation +// of the object's permission bits ( e.g. "drwxr-x--x" ), UID, +// size, and last access time. Does not add the name of the FSO +// +// Return type : TSTRING& -- reference to input buffer +// +// Argument : TSTRING& strBuf -- buffer. GetDesription will use it to allocate space. +// +TSTRING& cFSPropDisplayer::GetDetails( const iFCO* const pfco, TSTRING& strBuf ) const +{ + TOSTRINGSTREAM sstr; + const cFCOPropVector pv = pfco->GetPropSet()->GetValidVector(); + + sstr << std::left; + + sstr << _T(" ") << std::setw( PROP_MODE_WIDTH ); + if( pv.ContainsItem( cFSPropSet::PROP_MODE ) ) + sstr << PropAsString( pfco, cFSPropSet::PROP_MODE ).c_str(); + else + sstr << _T("XXXXXXXXX"); + + sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH ); + if( pv.ContainsItem( cFSPropSet::PROP_UID ) ) + sstr << PropAsString( pfco, cFSPropSet::PROP_UID ).c_str(); + else + sstr << _T("XXXXXXXXX"); + + sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH ); + if( pv.ContainsItem( cFSPropSet::PROP_SIZE ) ) + sstr << PropAsString( pfco, cFSPropSet::PROP_SIZE ).c_str(); + else + sstr << _T("XXX"); + + sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH ); + if( pv.ContainsItem( cFSPropSet::PROP_MTIME ) ) + sstr << PropAsString( pfco, cFSPropSet::PROP_MTIME ).c_str(); + else + sstr << _T("XXXXXXXXXXXXXXXXX"); + + strBuf = sstr.str(); + return strBuf; +} + + + +void cFSPropDisplayer::InitForFCO( const iFCO* const ifco ) +{ + ASSERT( ifco != 0); + + cFCOPropVector v = ifco->GetPropSet()->GetValidVector(); + int vSize = v.GetSize(); + for( int i = 0; i < vSize; i++ ) + { + if( v.ContainsItem( i ) ) + { + InitForProp( ifco, i ); + } + } +} + + +void cFSPropDisplayer::InitForProp( const iFCO* const pFCO, const int propIdx) +{ + ASSERT( pFCO != 0); + + switch( propIdx ) + { + case cFSPropSet::PROP_UID: + { + const int64& i64UID = static_cast( pFCO->GetPropSet()->GetPropAt( cFSPropSet::PROP_UID ) )->GetValue(); + + // check if prop is in table. if it is, then don't hit the FS + TSTRING tstrDummy; + if( ! GetUsername( i64UID, tstrDummy ) ) + { + TSTRING tstrUsername; + if( iFSServices::GetInstance()->GetOwnerForFile( pFCO->GetName().AsString(), tstrUsername ) ) + AddUsernameMapping ( i64UID, tstrUsername ); + else + AddUsernameMapping ( i64UID, _T("") ); // on failure, enter error value into mapping so we don't search for this value again. + } + } + break; + case cFSPropSet::PROP_GID: + { + const int64& i64GID = static_cast( pFCO->GetPropSet()->GetPropAt( cFSPropSet::PROP_GID ) )->GetValue(); + + // check if prop is in table. if it is, then don't hit the FS + TSTRING tstrDummy; + if( ! GetGroupname( i64GID, tstrDummy ) ) + { + TSTRING tstrGroupname; + if( iFSServices::GetInstance()->GetGroupForFile( pFCO->GetName().AsString(), tstrGroupname ) ) + AddGroupnameMapping( i64GID, tstrGroupname ); + else + AddGroupnameMapping( i64GID, _T("") ); // on failure, enter error value into mapping so we don't search for this value again. + } + } + break; + default: + // right now nothing else needs to be done for the other props + break; + } +} + +TSTRING cFSPropDisplayer::PropAsString( const iFCO* const pFCO, const int propIdx, int iOffset, int iWidth ) +{ + if( mpvPropsWeDisplay.ContainsItem( propIdx ) && mbLazy ) + { + InitForProp( pFCO, propIdx ); + } + // run the const version of PropAsString + return ((const cFSPropDisplayer*)this)->PropAsString(pFCO, propIdx, iOffset, iWidth); +} + +TSTRING cFSPropDisplayer::PropAsString( const iFCO* const pFCO, const int propIdx, int iOffset, int iWidth ) const +{ + TSTRING strProp = _T(""); + + ASSERT( pFCO != 0); + + // get prop pointer + const iFCOProp* pProp = pFCO->GetPropSet()->GetPropAt( propIdx ); + + // if we know how to display prop + if( pProp->GetType() != cFCOUndefinedProp::GetInstance()->GetType() && + mpvPropsWeDisplay.ContainsItem( propIdx ) ) + { + switch( propIdx ) + { + case cFSPropSet::PROP_BLOCK_SIZE: + case cFSPropSet::PROP_BLOCKS: + case cFSPropSet::PROP_SIZE: + case cFSPropSet::PROP_NLINK: + { + const cFCOPropInt64* const pTypedProp = static_cast(pProp); + cTWLocale::FormatNumber( pTypedProp->GetValue(), strProp ); + } + break; + case cFSPropSet::PROP_ATIME: + case cFSPropSet::PROP_MTIME: + case cFSPropSet::PROP_CTIME: + { + const cFCOPropInt64* const pTypedProp = static_cast(pProp); + int64 i64 = pTypedProp->GetValue(); + cTWLocale::FormatTime( i64, strProp ); + } + break; + case cFSPropSet::PROP_MODE: + { + const cFCOPropUint64* const pTypedProp = static_cast(pProp); + ASSERT( pTypedProp != 0); + + iFSServices::GetInstance()->ConvertModeToString( pTypedProp->GetValue(), strProp ); + } + break; + case cFSPropSet::PROP_UID: + { + const cFCOPropInt64* const pTypedProp = static_cast(pProp); + ASSERT( pTypedProp != 0); + if( GetUsername( pTypedProp->GetValue(), strProp ) ) + { + TSTRINGSTREAM ostr; + ostr << strProp << _T(" (") << (int32) pTypedProp->GetValue() << _T(")"); + strProp = ostr.str(); + } + else + strProp = pProp->AsString(); + } + break; + case cFSPropSet::PROP_GID: + { + const cFCOPropInt64* const pTypedProp = static_cast(pProp); + ASSERT( pTypedProp != 0); + if( GetGroupname( pTypedProp->GetValue(), strProp ) ) + { + TSTRINGSTREAM ostr; + ostr << strProp << _T(" (") << (int32) pTypedProp->GetValue() << _T(")"); + strProp = ostr.str(); + } + else + strProp = pProp->AsString(); + } + break; + default: + ASSERT( false ); // mpvPropsWeDisplay should contain one of the above + break; + } + } + else // we don't know how to display prop, so let prop display itself + { + strProp = pProp->AsString(); + } + + return( strProp ); +} + +void cFSPropDisplayer::Write( iSerializer* pSerializer ) const +{ + mpvPropsWeDisplay.Write( pSerializer ); + pSerializer->WriteInt32( mbLazy ? 1 : 0 ); + + + // stuff + { + // write UID mapping + pSerializer->WriteInt32( uidToUsername.size() ); + for( INT64_TO_STRING_MAP::const_iterator iterUid = uidToUsername.begin(); iterUid != uidToUsername.end(); iterUid++ ) + { + pSerializer->WriteInt64( iterUid->first ); + pSerializer->WriteString( iterUid->second ); + } + + // write GID mapping + pSerializer->WriteInt32( gidToGroupname.size() ); + for( INT64_TO_STRING_MAP::const_iterator iterGid = gidToGroupname.begin(); iterGid != gidToGroupname.end(); iterGid++ ) + { + pSerializer->WriteInt64( iterGid->first ); + pSerializer->WriteString( iterGid->second ); + } + } +} + +void cFSPropDisplayer::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Property Displayer Read"))); + + mpvPropsWeDisplay.Read( pSerializer ); + + int32 iDummy; + pSerializer->ReadInt32( iDummy ); + mbLazy = iDummy == 0 ? false : true; + + // stuff + { + int32 nValues; + int64 key; + TSTRING val; + int i; + + // read UID hashtable + pSerializer->ReadInt32( nValues ); + for( i = 0; i < nValues; i++ ) + { + pSerializer->ReadInt64( key ); + pSerializer->ReadString( val ); + AddUsernameMapping( key, val ); + } + + // read GID hashtable + pSerializer->ReadInt32( nValues ); + for( i = 0; i < nValues; i++ ) + { + pSerializer->ReadInt64( key ); + pSerializer->ReadString( val ); + AddGroupnameMapping( key, val ); + } + } +} + + + + + +////////////////////////////////////////////// +// Lookup functions +////////////////////////////////////////////// + +bool cFSPropDisplayer::GetUsername( const int64& i64uid, TSTRING& tstrUsername ) const +{ + bool fFound = false; + + INT64_TO_STRING_MAP::const_iterator iter = uidToUsername.find( i64uid ); + + if( iter != uidToUsername.end() ) + { + fFound = true; + tstrUsername = iter->second; + } + + return( fFound && !tstrUsername.empty() ); +} + +bool cFSPropDisplayer::GetGroupname( const int64& i64gid, TSTRING& tstrGroupname ) const +{ + bool fFound = false; + + INT64_TO_STRING_MAP::const_iterator iter = gidToGroupname.find( i64gid ); + + if( iter != gidToGroupname.end() ) + { + fFound = true; + tstrGroupname = iter->second; + } + + return( fFound && !tstrGroupname.empty() ); +} + +////////////////////////////////////////////// +// Addition functions +////////////////////////////////////////////// + +bool cFSPropDisplayer::AddUsernameMapping( const int64& i64uid, const TSTRING& tstrUsername ) +{ + std::pair ret = uidToUsername.insert( INT64_TO_STRING_MAP::value_type( i64uid, tstrUsername ) ); + return( ret.second = false ); // returns true if key didn't exist before +} + +bool cFSPropDisplayer::AddGroupnameMapping( const int64& i64gid, const TSTRING& tstrGroupname ) +{ + std::pair ret = gidToGroupname.insert( INT64_TO_STRING_MAP::value_type( i64gid, tstrGroupname ) ); + return( ret.second = false ); // returns true if key didn't exist before +} + + diff --git a/src/fs/fspropdisplayer.h b/src/fs/fspropdisplayer.h new file mode 100644 index 0000000..631281f --- /dev/null +++ b/src/fs/fspropdisplayer.h @@ -0,0 +1,150 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropdisplayer.h +// + +#ifndef __FSPROPDISPLAYER_H +#define __FSPROPDISPLAYER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __FCOPROPDISPLAYER_H +#include "fco/fcopropdisplayer.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "serializable.h" +#endif + +#ifndef __FCOPROPVECTOR_H +#include "fco/fcopropvector.h" +#endif + +#ifndef __FCOPROP_H +#include "fco/fcoprop.h" +#endif + +#ifndef __HASHTABLE_H +#include "core/hashtable.h" +#endif + +#ifndef __FCONAME_H +#include "fco/fconame.h" +#endif + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class iFCO; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + + +// +// cFSPropDisplayer +// + +class cFSPropDisplayer : public iFCOPropDisplayer +{ +public: + DECLARE_TYPEDSERIALIZABLE() + + cFSPropDisplayer(); + virtual ~cFSPropDisplayer(); + + virtual iFCOPropDisplayer* Clone() const; + + virtual void Merge( const iFCOPropDisplayer* const ppd ); + virtual const cFCOPropVector& GetPropsConverted() const; + virtual TSTRING PropAsString(const iFCO* const pFCO, const int propIdx, int iOffset = 0, int iWidth = 0 ) const ; + virtual TSTRING PropAsString( const iFCO* const pFCO, int const propIdx, int iOffset = 0, int iWidth = 0 ); + virtual bool IsMultiLineProp( int propID ) const; + virtual TSTRING& GetDetails( const iFCO* const pfco, TSTRING& strBuf ) const ; + virtual TSTRING& GetDetailsHeader( TSTRING& strBuf, int iMargin ) const; + virtual void InitForProp(const iFCO* const pFCO, const int propIdx); + virtual void InitForFCO( const iFCO* const ifco ); + virtual void SetLazy( const bool bLazy = true ); + virtual bool GetLazy() const; + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +private: + void AddMapping( const iFCOProp* const pProp, const TSTRING& tstrValue, const int propTypeEnum ); + // pass in a property value and its string representation. for instance: ( FS::PROP_UID --> username ) + + + cFCOPropVector mpvPropsWeDisplay; // if a given prop in this vector is valid, then this class + // can do a PropAsString that's different from iFCOProp::AsString() + bool mbLazy; + + typedef std::map< int64, TSTRING > INT64_TO_STRING_MAP; + + bool GetUsername( const int64& i64uid, TSTRING& tstrUsername ) const; + bool GetGroupname( const int64& i64uid, TSTRING& tstrGroupname ) const; + bool AddUsernameMapping ( const int64& i64ID, const TSTRING& tstrUsername ); + bool AddGroupnameMapping( const int64& i64ID, const TSTRING& tstrGroupname ); + + // storage for conversion stuff + INT64_TO_STRING_MAP uidToUsername; + INT64_TO_STRING_MAP gidToGroupname; + + friend class cTestFSPropDisplayer; + + enum Widths + { + PROP_MODE_WIDTH = 11, + PROP_OWNER_WIDTH = 20, + PROP_SIZE_WIDTH = 10, + PROP_MTIME_WIDTH = 10 + }; +}; + + +#endif //__FSPROPDISPLAYER_H + diff --git a/src/fs/fspropdisplayer_t.cpp b/src/fs/fspropdisplayer_t.cpp new file mode 100644 index 0000000..fb62351 --- /dev/null +++ b/src/fs/fspropdisplayer_t.cpp @@ -0,0 +1,133 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropdisplayer_t -- cFSPropDisplayer test driver + +#include "stdfs.h" +#include "fspropdisplayer.h" +#include "fspropcalc.h" +#include "fsobject.h" +#include "test/test.h" +#include "core/serializerimpl.h" + +class cTestFSPropDisplayer +{ +public: + static void Test(); +}; + + +void TestFSPropDisplayer() +{ + cTestFSPropDisplayer::Test(); +} + + +void cTestFSPropDisplayer::Test() +{ + char i; + cDebug d("TestFSPropDisplayer"); + + cFSPropDisplayer* pPD = new cFSPropDisplayer(); + + for( i = 0; i < 26; i++ ) + { + TCHAR c; + + c = i + 'a'; + pPD->AddUsernameMapping( i, TSTRING( 5, c ) ); + c = i + 'A'; + pPD->AddGroupnameMapping( i, TSTRING( 5, c ) ); + } + + cFSPropDisplayer* pPDNew = new cFSPropDisplayer(); + + for( i = 1; i < 26; i++ ) + { + TCHAR c; + + c = i + 'a'; + pPDNew->AddUsernameMapping( i, TSTRING( 10, c ) ); + c = i + 'A'; + pPDNew->AddGroupnameMapping( i, TSTRING( 10, c ) ); + } + + pPDNew->Merge( pPD ); + + /* + //////////////////////// + // write pd + cFileArchive outFile; + outFile.OpenReadWrite(_T("c:\\tmp\\tmp.pd")); + cSerializerImpl outSer(outFile, cSerializerImpl::S_WRITE); + + outSer.Init(); + + pPD->Write( &outSer ); + outSer.Finit(); + + outFile.Close(); + + + //////////////////////// + // read pd + cFileArchive inFile; + inFile.OpenRead(_T("c:\\tmp\\tmp.pd")); + cSerializerImpl inSer(inFile, cSerializerImpl::S_READ); + + cFSPropDisplayer* pPDNew = new cFSPropDisplayer(); + inSer.Init(); + + pPDNew->Read( &inSer ); + inSer.Finit(); + */ + + TSTRING strRet; + for( i = 0; i < 26; i++ ) + { + if( pPDNew->GetUsername( i, strRet ) ) + d.TraceDebug( "username for uid %d: <%s>\n", i, strRet.c_str() ); + else + d.TraceDebug( "no username for uid %d\n", i ); + + if( pPDNew->GetGroupname( i, strRet ) ) + d.TraceDebug( "groupname for gid %d: <%s>\n", i, strRet.c_str() ); + else + d.TraceDebug( "no groupname for gid %d\n", i ); + + d.TraceDebug("\n"); + } + + + return; +} + diff --git a/src/fs/fspropset.cpp b/src/fs/fspropset.cpp new file mode 100644 index 0000000..3850bb5 --- /dev/null +++ b/src/fs/fspropset.cpp @@ -0,0 +1,403 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropset.cpp + +#include "stdfs.h" + +#include "fspropset.h" + +#include "core/debug.h" +#include "core/serializer.h" +#include "fco/fcoundefprop.h" +#include "core/errorutil.h" + +// string table stuff +#include "fsstrings.h" + +//############################################################################# +// cFCOPropFileType +//############################################################################# +TSTRING cFCOPropFileType::AsString() const +{ + static int fileTypes [] = + { + fs::STR_FT_INVALID, + fs::STR_FT_FILE, + fs::STR_FT_DIR, + fs::STR_FT_BLOCKDEV, + fs::STR_FT_CHARDEV, + fs::STR_FT_SYMLINK, + fs::STR_FT_FIFO, + fs::STR_FT_SOCK + }; + + int32 fileType = GetValue(); + if((fileType > cFSPropSet::FT_INVALID) && (fileType < cFSPropSet::FT_NUMITEMS)) + return TSS_GetString( cFS, fileTypes[fileType] ); + else + return TSS_GetString( cFS, fileTypes[cFSPropSet::FT_INVALID] ); +} + + +//############################################################################# +// cFSPropSet +//############################################################################# + +IMPLEMENT_TYPEDSERIALIZABLE(cFSPropSet, _T("cFSPropSet"), 0, 1); + +/////////////////////////////////////////////////////////////////////////////// +// the names of all the properties +// TODO -- put these in a class-static hash table of something of the like so that +// name lookups are constant time -- mdb +/////////////////////////////////////////////////////////////////////////////// +static int cFSPropSet_PropNames [] = +{ + fs::STR_PROP_FILETYPE, + fs::STR_PROP_DEV, + fs::STR_PROP_RDEV, + fs::STR_PROP_INODE, + fs::STR_PROP_MODE, + fs::STR_PROP_NLINK, + fs::STR_PROP_UID, + fs::STR_PROP_GID, + fs::STR_PROP_SIZE, + fs::STR_PROP_ATIME, + fs::STR_PROP_MTIME, + fs::STR_PROP_CTIME, + fs::STR_PROP_BLOCK_SIZE, + fs::STR_PROP_BLOCKS, + fs::STR_PROP_GROWING_FILE, + fs::STR_PROP_CRC32, + fs::STR_PROP_MD5, + fs::STR_PROP_SHA, + fs::STR_PROP_HAVAL, + fs::STR_PROP_ACL +}; + +/////////////////////////////////////////////////////////////////////////////// +// TraceContents +/////////////////////////////////////////////////////////////////////////////// +void cFSPropSet::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFSPropSet::TraceContents"); + + TOSTRINGSTREAM ostr; + ostr << _T("File Sysytem Prop Set: "); + for(int i=0; iGetType() == CLASS_TYPE(cFSPropSet)); + + // first, modify my valid vector... + mValidProps |= propsToCopy; + + for(int i=0; i < GetNumFSProps(); i++) + { + if(propsToCopy.ContainsItem(i)) + { + ASSERT( pSrc->GetValidVector().ContainsItem( i ) ); + const iFCOProp* pProp = pSrc->GetPropAt(i); + + if (pProp->GetType() != cFCOUndefinedProp::GetInstance()->GetType()) + { + GetPropAt(i)->Copy( pProp ); + mUndefinedProps.RemoveItem(i); + } + else + mUndefinedProps.AddItem(i); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Invalidate +/////////////////////////////////////////////////////////////////////////////// +void cFSPropSet::InvalidateProp(int index) +{ + ASSERT((index >= 0) && (index < GetNumProps())); + mValidProps.RemoveItem(index); +} + +void cFSPropSet::InvalidateAll() +{ + mValidProps.Clear(); +} + +void cFSPropSet::InvalidateProps(const cFCOPropVector& propsToInvalidate) +{ + cFCOPropVector inBoth = mValidProps; + inBoth &= propsToInvalidate; + mValidProps ^= inBoth; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetNumFSProps +/////////////////////////////////////////////////////////////////////////////// +int cFSPropSet::GetNumFSProps() +{ + return PROP_NUMITEMS; +} + +/////////////////////////////////////////////////////////////////////////////// +// ctors. dtor, operator= +/////////////////////////////////////////////////////////////////////////////// +cFSPropSet::cFSPropSet() : + mValidProps(cFSPropSet::PROP_NUMITEMS), + mUndefinedProps(cFSPropSet::PROP_NUMITEMS) +{ + // TODO: do I want to zero out all the property values here? +} + +cFSPropSet::~cFSPropSet() +{ + +} + +cFSPropSet::cFSPropSet(const cFSPropSet& rhs) : + mValidProps(cFSPropSet::PROP_NUMITEMS) +{ + *this = rhs; +} + +const cFSPropSet& cFSPropSet::operator=(const cFSPropSet& rhs) +{ + mValidProps = rhs.GetValidVector(); + mUndefinedProps = rhs.mUndefinedProps; + + for(int i=0; i < PROP_NUMITEMS; i++) + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Copy( ((cFSPropSet&)rhs).GetPropAt(i) ); // call non-const GetPropAt for rhs + // don't want it to assert ContainsItem + return *this; +} + +const cFCOPropVector& cFSPropSet::GetValidVector() const +{ + return mValidProps; +} + +int cFSPropSet::GetNumProps() const +{ + return PROP_NUMITEMS; +} + +int cFSPropSet::GetPropIndex(const TCHAR* name) const +{ + for(int i=0; i= 0) && (index < GetNumProps())); + return TSS_GetString( cFS, cFSPropSet_PropNames[index]); +} + +const iFCOProp* cFSPropSet::GetPropAt(int index) const +{ + // the specified property had better have a valid value... + ASSERT((index >= 0) && (index < GetNumProps())); + ASSERT(mValidProps.ContainsItem(index)); + + if (mUndefinedProps.ContainsItem(index)) + { + return cFCOUndefinedProp::GetInstance(); + } + + switch(index) + { + case PROP_FILETYPE: + return &mFileType; + case PROP_DEV: + return &mDev; + case PROP_RDEV: + return &mRDev; + case PROP_INODE: + return &mInode; + case PROP_MODE: + return &mMode; + case PROP_NLINK: + return &mNLink; + case PROP_UID: + return &mUID; + case PROP_GID: + return &mGID; + case PROP_SIZE: + return &mSize; + case PROP_ATIME: + return &mAccessTime; + case PROP_MTIME: + return &mModifyTime; + case PROP_CTIME: + return &mCreateTime; + case PROP_BLOCK_SIZE: + return &mBlockSize; + case PROP_BLOCKS: + return &mBlocks; + case PROP_GROWING_FILE: + return &mGrowingFile; + case PROP_CRC32: + return &mCRC32; + case PROP_MD5: + return &mMD5; + case PROP_SHA: + return &mSHA; + case PROP_HAVAL: + return &mHAVAL; + case PROP_ACL: + ASSERT( false ); // unimplemented + return NULL; + default: + { + // bad parameter passed to GetPropAt + ASSERT(false); + } + } + return NULL; +} + +// TODO -- it sucks duplicating code like this! -- mdb +iFCOProp* cFSPropSet::GetPropAt(int index) +{ + // the specified property had better have a valid value... + ASSERT((index >= 0) && (index < GetNumProps())); + // don't assert for non-const GetPropAt() because we might want to get a non-valid + // property for copying + //ASSERT(mValidProps.ContainsItem(index)); + + if (mUndefinedProps.ContainsItem(index)) + { + return cFCOUndefinedProp::GetInstance(); + } + + switch(index) + { + case PROP_FILETYPE: + return &mFileType; + case PROP_DEV: + return &mDev; + case PROP_RDEV: + return &mRDev; + case PROP_INODE: + return &mInode; + case PROP_MODE: + return &mMode; + case PROP_NLINK: + return &mNLink; + case PROP_UID: + return &mUID; + case PROP_GID: + return &mGID; + case PROP_SIZE: + return &mSize; + case PROP_ATIME: + return &mAccessTime; + case PROP_MTIME: + return &mModifyTime; + case PROP_CTIME: + return &mCreateTime; + case PROP_BLOCK_SIZE: + return &mBlockSize; + case PROP_BLOCKS: + return &mBlocks; + case PROP_GROWING_FILE: + return &mGrowingFile; + case PROP_CRC32: + return &mCRC32; + case PROP_MD5: + return &mMD5; + case PROP_SHA: + return &mSHA; + case PROP_HAVAL: + return &mHAVAL; + case PROP_ACL: + ASSERT( false ); // unimplemented + return NULL; + default: + { + // bad parameter passed to GetPropAt + ASSERT(false); + } + } + return NULL; + +} + +void cFSPropSet::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("FS Property Set Read"))); + + mValidProps.Read(pSerializer); + mUndefinedProps.Read(pSerializer); + + for (int i=0; i < PROP_NUMITEMS; i++) + { + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Read(pSerializer); + } +} + +void cFSPropSet::Write(iSerializer* pSerializer) const +{ + mValidProps.Write(pSerializer); + mUndefinedProps.Write(pSerializer); + + for (int i=0; i < PROP_NUMITEMS; i++) + { + if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i)) + GetPropAt(i)->Write(pSerializer); + } +} + diff --git a/src/fs/fspropset.h b/src/fs/fspropset.h new file mode 100644 index 0000000..e91b1cb --- /dev/null +++ b/src/fs/fspropset.h @@ -0,0 +1,176 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fspropset.h -- file system objects' property set objects +// +// cFSPropSet -- base class with all of the common properties +#ifndef __FSPROPSET_H +#define __FSPROPSET_H + +#ifndef __FCOPROPSET_H +#include "fco/fcopropset.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif +#ifndef __FCOPROPIMPL_H +#include "fco/fcopropimpl.h" +#endif +#ifndef __SIGNATURE_H +#include "fco/signature.h" +#endif +#ifndef __PROPSET_H +#include "fco/propset.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// cFCOPropFileType -- a property that represents a file type. Is is really just +// an int32 that overrides the AsString() method to display the file type +/////////////////////////////////////////////////////////////////////////////// +class cFCOPropFileType : public cFCOPropInt32 +{ +public: + virtual TSTRING AsString() const; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFSPropSet +/////////////////////////////////////////////////////////////////////////////// +class cFSPropSet : public iFCOPropSet +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + // file system property enumeration.. + enum + { + PROP_FILETYPE = 0, + PROP_DEV, + PROP_RDEV, + PROP_INODE, + PROP_MODE, + PROP_NLINK, + PROP_UID, + PROP_GID, + PROP_SIZE, + PROP_ATIME, + PROP_MTIME, + PROP_CTIME, + PROP_BLOCK_SIZE, + PROP_BLOCKS, + PROP_GROWING_FILE, // a hack to detect growing files; this holds the same thing as PROP_SIZE + PROP_CRC32, + PROP_MD5, + PROP_SHA, + PROP_HAVAL, + PROP_ACL, + + PROP_NUMITEMS + }; + + // the type of file this is + enum FileType + { + FT_INVALID = 0, + FT_FILE, + FT_DIR, + FT_BLOCKDEV, + FT_CHARDEV, + FT_SYMLINK, + FT_FIFO, + FT_SOCK, + FT_NUMITEMS + }; + + + cFSPropSet(); + cFSPropSet(const cFSPropSet& rhs); + virtual ~cFSPropSet(); + + const cFSPropSet& operator=(const cFSPropSet& rhs); + + virtual const cFCOPropVector& GetValidVector() const ; + virtual int GetNumProps () const ; + virtual int GetPropIndex(const TCHAR* name) const; + virtual TSTRING GetPropName (int index) const; + virtual const iFCOProp* GetPropAt(int index) const; + virtual iFCOProp* GetPropAt(int index) ; + virtual void InvalidateProp(int index); + virtual void InvalidateProps(const cFCOPropVector& propsToInvalidate) ; + virtual void InvalidateAll(); + virtual void CopyProps(const iFCOPropSet* pSrc, const cFCOPropVector& propsToCopy); + + static int GetNumFSProps(); + // convenience function that returns the number of properties FSPropSets have without needing + // to create one. This is useful in creating property vectors, since you need to know the size... + + // note that file type and normalized time are redundant properties (that is, they are derived from + // the values of other properties) but their values are dependent on the file system the fsobject + // came from, so they must be set during property calculation + + // Get/Set functions for all the properties + PROPERTY(cFCOPropFileType, FileType, PROP_FILETYPE) // file type enumeration above + PROPERTY(cFCOPropUint64, Dev, PROP_DEV) //st_dev -- the device number of the disk + PROPERTY(cFCOPropUint64, RDev, PROP_RDEV) //st_rdev -- the device number of character or block file + PROPERTY(cFCOPropUint64, Inode, PROP_INODE) //st_ino -- the indode number + PROPERTY(cFCOPropUint64, Mode, PROP_MODE) //st_mode -- the file's mode; also indicates whether it is a directory or a file + PROPERTY(cFCOPropInt64, NLink, PROP_NLINK) //st_nlink -- number of links to this file + PROPERTY(cFCOPropInt64, UID, PROP_UID) //st_uid -- uid who owns the file + PROPERTY(cFCOPropInt64, GID, PROP_GID) //st_gid -- gid who owns the file + PROPERTY(cFCOPropInt64, Size, PROP_SIZE) //st_size -- the size of the file + PROPERTY(cFCOPropInt64, AccessTime, PROP_ATIME) //st_atime -- last access time + PROPERTY(cFCOPropInt64, ModifyTime, PROP_MTIME) //st_mtime -- last modify time + PROPERTY(cFCOPropInt64, CreateTime, PROP_CTIME) //st_ctime -- create time + PROPERTY(cFCOPropInt64, BlockSize, PROP_BLOCK_SIZE)//st_blksize + PROPERTY(cFCOPropInt64, Blocks, PROP_BLOCKS) //st_blocks + PROPERTY(cFCOPropGrowingFile, GrowingFile, PROP_GROWING_FILE) //growing file property; synonym for Size above. + PROPERTY_OBJ(cCRC32Signature, CRC32, PROP_CRC32) + PROPERTY_OBJ(cMD5Signature, MD5, PROP_MD5) + PROPERTY_OBJ(cSHASignature, SHA, PROP_SHA) + PROPERTY_OBJ(cHAVALSignature, HAVAL, PROP_HAVAL) + //PROPERTY_OBJ(cUnixACL, ACL, PROP_ACL) // will eventually be implememented + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + // debugging method + virtual void TraceContents(int dl = -1) const; + +private: + cFCOPropVector mValidProps; // all the properties that have been evaluated + cFCOPropVector mUndefinedProps; // properties that have been measured but have undefined values +}; + +#endif + diff --git a/src/fs/fspropset_t.cpp b/src/fs/fspropset_t.cpp new file mode 100644 index 0000000..a5fe64c --- /dev/null +++ b/src/fs/fspropset_t.cpp @@ -0,0 +1,96 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fspropset_t.cpp -- FSPropSet test driver +#include "stdfs.h" +#include "fspropset.h" +#include "test/test.h" +#include "core/debug.h" + + +/////////////////////////////////////////////////////////////////////////////// +// PrintPropVector -- function that prints the contents of a cFCOPropVector +// TODO: We might want to add this functionality to the property vector some +// day... +/////////////////////////////////////////////////////////////////////////////// +static void PrintPropVector(const cFCOPropVector& v, cDebug& d) +{ + TOSTRINGSTREAM stream; + for(int i=0; i" is now the fconame/specmask separator + * attribute lists now contain comma-separated attributes + * quoted strings use C++-style escaping (char (e.g. \n, \"), hex (e.g. \x8E230A), oct(e.g. \271) ) + + TODO: UNICODE +*/ + +%start policy +%% + +/*----------------------------------------------------------------------------- + * policy rules + * + * these productions are responsible for creating the list of rules. each completed rule + * is added to either the "omit list" or the "rule list" + * + */ + +policy + : statement_list + ; + + +statement_list + : statement_list statement + | statement + ; + +opt_statement_list + : statement_list + | /* empty */ + ; + +statement + : variable_assignment TWP_SEMICOLON + | rule TWP_SEMICOLON + | TWP_SEMICOLON + | directive_block + ; + +/*----------------------------------------------------------------------------- + * directives + */ + +directive_block + : TWP_IFHOST host_name_list opt_statement_list opt_else_host TWP_ENDIF + | TWP_ERROR string + | TWP_ECHO string + ; + +host_name_list + : host_name_list TWP_OROR host_name + | host_name + ; + +opt_else_host + : TWP_ELSE opt_statement_list + | /* empty */ + ; + + +/*----------------------------------------------------------------------------- + * variable assignment + */ + +variable_assignment + : TWP_DOLLAR TWP_LPAREN string TWP_RPAREN TWP_EQUALS string + ; + + +/*----------------------------------------------------------------------------- + * rules + */ + +rule + : fco_name TWP_RARROW spec_masks + | TWP_BANG fco_name /* stop point */ + ; + +spec_masks + : prop_vector opt_spec_attributes + ; + + +/*----------------------------------------------------------------------------- + * attributes + */ + +opt_spec_attributes + : TWP_LPAREN attribute_list_with_opt_trailing_semicolon TWP_RPAREN + | /* empty */ + ; + +attribute_list_with_opt_trailing_semicolon + : attribute_list opt_semicolon + ; + +attribute_list + : attribute_list TWP_COMMA attribute + | attribute + ; +attribute + : attribute_name attribute_value + ; + +opt_semicolon + : TWP_SEMICOLON + | /* empty */ + ; + + +/*----------------------------------------------------------------------------- + * properties + */ + +prop_vector + : prop_vector_item prop_vector + | prop_vector_item + ; + +prop_vector_item + : string + ; + +/*----------------------------------------------------------------------------- + * variables + */ + +variable + : TWP_DOLLAR TWP_LPAREN string TWP_RPAREN + ; + +/*----------------------------------------------------------------------------- + * strings + */ + +attribute_name + : string + ; + +attribute_value + : string + ; + +fco_name + : string + ; + +host_name + : string + ; + +string + : TWP_STRING + | variable + ; + +%% \ No newline at end of file diff --git a/src/parser/policy.y b/src/parser/policy.y new file mode 100644 index 0000000..910c79f --- /dev/null +++ b/src/parser/policy.y @@ -0,0 +1,810 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +/////////////////////////////////////////////////////////////////////////////// +// policy.y -- yacc grammar for parsing policy language +// + + INTERESTING STUFF: + --------------------- + * all whitespace is removed from input + * token "@@end" is taken as the logical end of policy file + * "->" is now the fconame/specmask separator + * attribute lists now contain comma-separated attributes + * quoted strings use C++-style escaping (char (e.g. \n, \"), hex (e.g. \x8E230A), oct(e.g. \271) ) + * default spec mask has name _T("default") + + TODO: UNICODE +*/ + +/* + * NOTE: prefix all token names with TWP_ to prevent #define name collisions + * (e.g., STRING is probably already defined by somebody...) + */ + +/* + * debugging hints: + * + * - if you see an error like this: "policy.y: line 308: Newline in string started at line 307" + * you are using a C++ style comment, that has a "n't" in it somewhere -- like this: + * // tell parent that we don't have any attributes + * either change it to C comment, or change "don't" to "do not". + * unbelievable, isn't it? MKS Yacc is a piece of crap. + * + * ghk 8/28/98 + * + */ + +%token TWP_COMMA +%token TWP_LPAREN +%token TWP_RPAREN +%token TWP_COMMENT +%token TWP_STRING +%token TWP_SEMICOLON +%token TWP_LBRACE +%token TWP_RBRACE +%token TWP_DEFAULT +%token TWP_PIPE +%token TWP_DOLLAR +%token TWP_BANG +%token TWP_PLUS +%token TWP_MINUS +%token TWP_DQUOTE +%token TWP_RARROW +%token TWP_SECTION +%token TWP_IFHOST +%token TWP_ELSE +%token TWP_ENDIF +%token TWP_ECHO +%token TWP_ERROR + +/* TODO: change TWP_XXX to TWP_ID_XXX for keyword */ +%token TWP_DEFINE +%token TWP_UNDEF +%token TWP_ELSE +%token TWP_ENDIF +%token TWP_CONTENTS +%token TWP_DBASEVERSION +%token TWP_ANDAND +%token TWP_OROR +%token TWP_BSLASH +%token TWP_ESCCHAR +%token TWP_QSTRING +%token TWP_EQUALS +%token TWP_GLOBAL_STRING + +%{ + +#include "stdtwparser.h" + +#include "core/debug.h" +#include "parserhelper.h" +#include "genreparseinfo.h" +#include "policyparser.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "fco/parsergenreutil.h" +#include "fco/fconametranslator.h" +#include "core/usernotify.h" + +#ifndef YYNEWLINE +# include "parser/yylex.h" +# include "parser/yyparse.h" +#endif + + +// global variables +int yaccdebuglevel; + +// in MKS Yacc in C++ mode, we need to explicitly declare yylavl +YYSTYPE yylval; + + +static TSTRING ConcatenateStrings( const std::list* plist ) +{ + TSTRING strRet; + for( std::list::const_iterator i = plist->begin(); i != plist->end(); i++ ) + strRet += *i; + return strRet; +} + +static std::list* MergeIntoList( std::list* plistLHS, const std::list* plistRHS ) +{ + for( std::list::const_iterator i = plistRHS->begin(); i != plistRHS->end(); i++ ) + plistLHS->push_back( *i ); + return plistLHS; +} + +%} + +/* this defines the lval values that are returned by each grammar rule */ + +%union { + class cParseString* mpString; // wrapper around TSTRING + class cParseStringList* mpStringList; + + class cParseRule* mpNode; // representation of FCOSpec + + class cParseSpecMask* mpSpecMask; // representation of specmask + class cParseSpecMaskList* mpSpecMaskList; // ...and a collection + + class cParseNamedAttr* mpAttr; // representation of an attribute + class cParseNamedAttrList* mpAttrList; // ...and a collection +}; + + +%type spec_masks + +%type attribute + +%type attribute_list +%type attribute_list_with_opt_trailing_comma +%type opt_spec_attributes + +/***************************************** +TODO: implement this when everthing else is done and the details have been hammered out +%type wildcard_spec_mask +%type default_spec_mask + +%type opt_wildcard_spec_mask_list + +%type fco_wildcard +*****************************************/ + + +%type fco_name +%type attribute_name +%type attribute_value +%type string +%type multi_string +%type global_multi_string +%type variable +%type variable_name +%type global_string +%type host_name +%type host_name_list +%type prop_vector + + +%start policy +%% + +/*----------------------------------------------------------------------------- + * policy rules + * + * these productions are responsible for creating the list of rules. each completed rule + * adds a cParseRule to either the "omit list" or the "rule list" + * + */ + +policy + : opt_statement_list + ; + +opt_statement_list + : statement_list + | /* empty */ + ; + +statement_list + : statement_list statement + | statement + ; + +statement + : variable_assignment TWP_SEMICOLON { cParserHelper::IncrementScopeStatementCount(); } + | global_variable_assignment TWP_SEMICOLON { cParserHelper::IncrementScopeStatementCount(); } + | rule TWP_SEMICOLON { cParserHelper::IncrementScopeStatementCount(); } + | TWP_SEMICOLON + | directive_block + | scoped_block + ; + +scoped_block + : TWP_LPAREN attribute_list_with_opt_trailing_comma TWP_RPAREN TWP_LBRACE + { + cDebug d("Parse::scope"); + + // create new scope + cAttrScopeInfo* pScopeInfo = new cAttrScopeInfo; + + // init scope info + pScopeInfo->SetAttributes( $2 ); + + // push onto scope stack + cParserHelper::PushScope( pScopeInfo ); + d.TraceDebug("push\n"); + } + opt_statement_list TWP_RBRACE + { + if( 0 == cParserHelper::GetScopeStatementCount() && iUserNotify::GetInstance()->GetVerboseLevel() == iUserNotify::V_VERBOSE ) + { + eParserNoStatementsInScope e; + e.SetFatality( false ); + cParserHelper::GetErrorBucket()->AddError( e ); + } + + cDebug d("Parse::scope"); + cParserHelper::PopScope(); + d.TraceDebug("pop\n"); + } + ; + +directive_block + : TWP_IFHOST host_name_list + { + cDebug d("Parse::#ifhost"); + + /* only look at this if we're not ignoring */ + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + if( cParserUtil::AnyOfTheseHostsExists( $2 ) ) + { + cPreprocessor::PushState( cPreprocessor::STATE_ACCEPT ); + } + else + { + cPreprocessor::PushState( cPreprocessor::STATE_IGNORE ); + } + d.TraceDebug(_T("\n")); + } + else + { + cPreprocessor::PushState( cPreprocessor::STATE_IGNORE ); + d.TraceDebug(_T("ignoring ifhost\n")); + } + } + opt_statement_list opt_else_host TWP_ENDIF + { + cDebug d("Parse::#endif"); + cPreprocessor::PopState(); + + delete $2; + } + | TWP_SECTION string + { + cDebug d("Parse::#section"); + + if( ! ( cPreprocessor::AtTopLevel() && cParserHelper::AtTopScope() ) ) + throw eParserSectionInsideBlock( *$2 ); + + cParserHelper::SetSection( *$2 ); + + delete $2; + } + | TWP_ERROR string + { + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT && !cParserHelper::ParseOnly() ) + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, $2->c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("\n") ); + YYRETURN(-1); + } + + delete $2; + } + | TWP_ECHO string + { + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT && !cParserHelper::ParseOnly() ) + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, $2->c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("\n") ); + } + + delete $2; + } + ; + +host_name_list + : host_name_list TWP_OROR host_name + { + $$ = $1; + $$->push_back( *$3 ); + } + | host_name + { + $$ = new cParseStringList; + $$->push_back( *$1 ); + } + ; + +opt_else_host + : TWP_ELSE + { + cDebug d("Parse::#else"); + + if( cPreprocessor::GetLastState() == cPreprocessor::STATE_ACCEPT ) + { + cPreprocessor::ToggleTopState(); + d.TraceDebug(_T("\n")); + } + else + { + d.TraceDebug(_T("ignoring #else\n")); + } + + } + opt_statement_list + | /* empty */ + ; + +variable_assignment + : variable_name TWP_EQUALS multi_string + { + cDebug d("Parse::variable_assignment"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring variable assignment\n")); + } + else + { + TSTRING strVal = ConcatenateStrings( $3 ); + d.TraceDebug("*** assigning <%s> to <%s>\n", $1->c_str(), strVal.c_str() ); + cParserHelper::GetGenreInfo()->InsertVariable( *$1, strVal ); + } + + delete $1; + delete $3; + } + ; + +global_variable_assignment + : global_string TWP_EQUALS global_multi_string + { + cDebug d("Parse::global variable_assignment"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring global variable assignment\n")); + } + else + { + TSTRING strVal = ConcatenateStrings( $3 ); + d.TraceDebug("*** assigning <%s> to <%s>\n", $1->c_str(), strVal.c_str() ); + cParserHelper::InsertGlobalVariable( *$1, strVal ); + } + + delete $1; + delete $3; + } + ; + +rule + : fco_name TWP_RARROW spec_masks + { + cDebug d("Parse::rule(fco_name TWP_RARROW spec_masks)"); + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring rule\n")); + } + else + { + // bind to children + cParseStringList *pnamelist = $1; + cParseRule *pnode = $3; + cFCOName fcoName; + + // create the fco name from string + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + pGU->InterpretFCOName( *pnamelist, fcoName ); + + if( ! pGU->IsAbsolutePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringRaw( fcoName ) ) ) + throw eParserRelativePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + else if( cParserHelper::GetGenreInfo()->RulePointAlreadyDefined( fcoName ) ) + throw eParserPointAlreadyDefined( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + + // assign parse node the name, attributes + pnode->SetName( fcoName ); + + d.TraceDebug("*** rule(%s: %d specifiers, default=%s) (%d named attributes) (is%s case sensitive)\n", + pnode->GetName().AsString().c_str(), pnode->GetNumSpecMasks(), + pnode->GetDefSpecMask().GetPropVectorString().c_str(), + pnode->GetNumNamedAttrs(), + iTWFactory::GetInstance()->GetNameInfo()->IsCaseSensitive() ? "" : " not" ); + + pnode->Dump(); + + // add to our lists + cParserHelper::GetGenreInfo()->AddStopPoint( fcoName ); + cParserHelper::GetGenreInfo()->AddRule( pnode ); + } + + delete $1; + /* do not delete $3 */ + } + | TWP_BANG fco_name /* stop point */ + { + cDebug d("Parse::rule(!fconame)"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring rule\n")); + } + else + { + // create the fco name from string + cFCOName fcoName; + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + pGU->InterpretFCOName( *$2, fcoName ); + + if( ! pGU->IsAbsolutePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringRaw( fcoName ) ) ) + throw eParserRelativePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + if( cParserHelper::GetGenreInfo()->RulePointAlreadyDefined( fcoName ) ) + throw eParserPointAlreadyDefined( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + + d.TraceDebug( "*** omit(%s)\n", fcoName.AsString().c_str() ); + + // add to stop list + cParserHelper::GetGenreInfo()->AddStopPoint( fcoName ); + } + + delete $2; + } + ; + +spec_masks + : prop_vector opt_spec_attributes + { + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + TSTRING strDefault = _T("default"); + cParseRule* pNode = new cParseRule( cParseSpecMask( strDefault, *$1, pGU ) ); + + pNode->SetAttrList( $2 ); + $2->MergeNoOverwrite( cParserHelper::GetGlobalAttrList() ); + + $$ = pNode; + } + + delete $1; + /* do not delete $2 */ + /* do not delete pNode */ + } +/****************************************** +* + TODO: implement this when everthing else is done and the details have been hammered out + | TWP_LBRACE opt_wildcard_spec_mask_list default_spec_mask TWP_RBRACE + { + cParseRule* pNode = new cParseRule( $3 ); + + pNode->SetSpecMaskList( $2 ); + + $$ = pNode; + } + | TWP_LBRACE opt_wildcard_spec_mask_list TWP_RBRACE + { + ASSERT( false ); + } +* +******************************************/ + ; + +opt_spec_attributes + : TWP_LPAREN attribute_list_with_opt_trailing_comma TWP_RPAREN + { + $$ = $2; + } + | /* empty */ + { + $$ = new cParseNamedAttrList; + } + ; + +/****************************************** +* +TODO: implement this when everthing else is done and the details have been hammered out +opt_wildcard_spec_mask_list + : opt_wildcard_spec_mask_list wildcard_spec_mask + { + $$ = $1; + if( $$ == NULL ) + { + $$ = new cParseSpecMaskList; ASSERT( $$ ); + } + + $$->Add( $2 ); + } + | { $$ = NULL; } + ; +* +******************************************/ + +attribute_list_with_opt_trailing_comma + : attribute_list opt_comma + { + $$ = $1; + } + ; + +attribute_list + : attribute_list TWP_COMMA attribute + { + cDebug d("Parse::attribute_list"); + ASSERT( $1 && $3 ); + + // add attribute to list + $1->Add( $3 ); + d.TraceDebug("added attribute (%s=%s)\n", $3->GetName().c_str(), $3->GetValue().c_str()); + + $$ = $1; + + /* do not delete $3 */ + } + | attribute + { + cDebug d("Parse::attribute_list"); + + cParseNamedAttrList *pAttrList = new cParseNamedAttrList; ASSERT( pAttrList ); + + pAttrList->Add( $1 ); + d.TraceDebug("added attribute (%s=%s)\n", $1->GetName().c_str(), $1->GetValue().c_str()); + + $$ = pAttrList; + } + ; +attribute + : attribute_name TWP_EQUALS attribute_value + { + cDebug d("Parse::attribute"); + + cParseNamedAttr *pAttr = new cParseNamedAttr( *$1, *$3 ); + ASSERT(pAttr); + + d.TraceDebug("attribute (%s=%s)\n", $1->c_str(), $3->c_str()); + $$ = pAttr; + + /* don't need strings anymore */ + delete $1; + delete $3; + } + ; + +/****************************************** +* +TODO: implement this when everthing else is done and the details have been hammered out + +wildcard_spec_mask + : fco_wildcard TWP_RARROW prop_vector opt_spec_attributes TWP_SEMICOLON + { + cDebug d("Parse::wildcard_spec_mask"); + + // create node, and attach specmask string and attributes + // the parent will merge this into the rest of the specmasks, and then delete it + cParseSpecMask *pSpecMask = new cParseSpecMask( *$1, *$3 ); ASSERT( pSpecMask ); + + // attach any named attributes + pSpecMask->SetAttrList( $4 ); + + + d.TraceAlways("condition(%s), value(%s), attributes(%d)\n", + $1->c_str(), + $3->c_str(), + pSpecMask->GetNumAttrs()); + + $$ = pSpecMask; + } + ; + +default_spec_mask + : TWP_DEFAULT TWP_RARROW prop_vector opt_spec_attributes TWP_SEMICOLON + { + cDebug d("Parse::default_spec_mask"); + + // create node, and attach specmask string and attributes + // the parent will merge this into the rest of the specmasks, and then delete it + cParseSpecMask *pDefMask = new cParseSpecMask(TSTRING("default"), *$3); ASSERT(pDefMask); + + // attach any named attributes + pDefMask->SetAttrList( $4 ); + + d.TraceAlways("propvector(%s), num attributes(%d)\n", pDefMask->GetPropVector().c_str(), + pDefMask->GetNumAttrs()); + + $$ = pDefMask; + } + ; +* +******************************************/ + +opt_comma + : TWP_COMMA + | /* empty */ + ; + + +variable + : TWP_DOLLAR TWP_LPAREN variable_name TWP_RPAREN + { + cDebug d( " parser::variable" ); + + cParseString* pVarValue = new cParseString; + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + // we want to replace the keyword with its value, (e.g. replacing ReadOnly + // with "pingus" (or whatever readonly means). So it is a rote replacement. + if( ! cParserHelper::GetGenreInfo()->LookupVariable( *$3, *pVarValue ) ) + throw eParserUseUndefVar( *$3 ); + + // return the lval + d.TraceDetail("--(STRING)--> got variable (%s) mapped to (%s)\n", + $3->c_str(), + pVarValue->c_str()); + } + + $$ = pVarValue; + + /* don't need string anymore */ + delete $3; + } + ; + + +/****************************************** +* +TODO: implement this when everthing else is done and the details have been hammered out +fco_wildcard + : TWP_STRING + { + // like "*.exe" + cDebug d(" parser::string(fco_wildcard)"); + d.TraceNever("--(STRING)--> got string (%s)\n", $1); + $$ = $1; + } + ; + +* +*******************************************/ + +prop_vector + : multi_string + { + $$ = new cParseString; + *$$ = ConcatenateStrings( $1 ); + delete $1; + } + ; + +attribute_name + : string + { + cDebug d(" parser::string(attribute_name)"); + $$ = $1; + } + ; + +attribute_value + : multi_string + { + $$ = new cParseString; + cDebug d(" parser::multi_string(attribute_value)"); + *$$ = ConcatenateStrings( $1 ); + delete $1; + } + ; + +fco_name + : multi_string + { + cDebug d(" parser::multi_string(fco_name)"); + $$ = $1; + } + | + multi_string TWP_PIPE multi_string + { + #if IS_WIN32 + ASSERT( 0 == _tcscmp( _T("NTREG"), cGenreSwitcher::GetInstance()->GenreToString( cGenreSwitcher::GetInstance()->CurrentGenre() ) ) ); + #endif + + $1->push_back( _T("|") ); + MergeIntoList( $1, $3 ); + $$ = $1; + + delete $3; + } + ; + +host_name + : string + { + /*not multistring because no eol delimiter */ + cDebug d(" parser::multi_string(host_name)"); + $$ = $1; + } + ; + +variable_name + : TWP_STRING + { + cDebug d(" parser::string(variable_name)"); + $$ = $1; + } + ; + + +multi_string + : multi_string string + { + $$->push_back( *$2 ); + delete $2; + } + | string + { + $$ = new cParseStringList; + $$->push_back( *$1 ); + delete $1; + } + ; + +global_multi_string + : global_multi_string global_string + { + $$->push_back( *$2 ); + delete $2; + } + | global_string + { + $$ = new cParseStringList; + $$->push_back( *$1 ); + delete $1; + } + ; + + +string + : TWP_STRING + { + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", $1); + $$ = $1; + } + | variable + { + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", $1); + $$ = $1; + } + ; + +global_string + : TWP_GLOBAL_STRING + { + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", $1); + $$ = $1; + } + ; +%% + diff --git a/src/parser/testfiles/directives.txt b/src/parser/testfiles/directives.txt new file mode 100644 index 0000000..4374975 --- /dev/null +++ b/src/parser/testfiles/directives.txt @@ -0,0 +1,135 @@ +# replace your_host with the name of your host. +# parser will echo YES1 through YES9 +# there's a problem with the parser if it echoes NO + +@@ifhost turd + @@error NO1 +@@else + @@echo +YES1; +@@endif + +@@ifhost crap || your_host||poo + + + @@ifhost turd + + @@ifhost your_host + @@error +NO2; + @@else + @@error +NO3; + @@endif + + @@error +NO4; + + @@else + + @@ifhost turd + @@error +NO5; + @@else + @@echo +YES2; + @@endif + + @@echo +YES3; + + @@endif + + + + @@ifhost your_host + + @@ifhost your_host + @@echo +YES4; + @@else + @@error +NO6; + @@endif + + @@echo +YES5; + + @@else + + @@ifhost your_host + @@error +NO7; + @@else + @@error +NO8; + @@endif + + @@error +NO9; + + @@endif + + @@ifhost your_host + @@echo +YES6; + @@else + @@error +NO10; + @@endif + + @@ifhost turd + @@error +NO11; + @@else + @@echo +YES7; + @@endif + + + @@ifhost your_host || poo + @@echo +YES8; + @@endif + + @@ifhost poo || your_host + @@echo +YES9; + @@endif + + @@ifhost poo + @@error +NO12; + @@endif + +@@else + + + @@ifhost turd + + @@ifhost your_host + @@error +NO13; + @@else + @@error +NO14; + @@endif + + @@error +NO16; + + @@else + + @@ifhost turd + @@error +NO16; + @@else + @@error +NO17; + @@endif + + @@error +NO18; + + @@endif + + @@ifhost turd + @@error +NO19; + @@else + @@error +NO20; + @@endif + + @@ifhost your_host + @@error +NO21; + @@else + @@error +NO22; + @@endif + + + @@ifhost turd + @@error +NO23; + @@else + @@error +NO24; + @@endif + + @@ifhost poo + @@error +NO25; + @@endif + +@@endif + + diff --git a/src/parser/testfiles/pol.txt b/src/parser/testfiles/pol.txt new file mode 100644 index 0000000..2b0accc --- /dev/null +++ b/src/parser/testfiles/pol.txt @@ -0,0 +1,100 @@ +/test -> +p; +/test2 -> +p-p ; +/test3 -> +pinugs-am ; +/test4 -> +pinugs---am ; +/test5 -> +pinugs-+-am ; + +# test weird file names +"/lost+\"found\"" -> +p ; + +# test quoted strings +"/q\n\xAfoo" -> +p ; + +# simple default policy +/simple -> +ppp; + +# variable +$(poo) = pinug; +/simplevar -> $(poo) ; + +$(turd) = /test6; +$(turd) -> $(poo); + +# named attributes +/namedattr -> +pinug (name /namedattr ) ; + +# multiple attributes +/namedattr2 -> +pinug (emailreport on, emailsendto genek, name /namedattr2, name4 val4, name5 val5 ); + +# test line continuations +/turd \ + ->\ + +p + ; +@@EnD + +/test -> +p; +"/te\x73t2" -> +p-p ; +"/te\163t3" -> +pinugs-am ; +"c:\\te\163t3\\" -> +pinugs-am ; +"c:\\te\"as\163t3\\" -> +pinugs-am ; +"/te\163t3" -> +pinugs-am ; +"/te\163t3" -> +pinugs-am ; +/test4 -> +pinugs---am ; +/test5 -> $(ReadOnly)s-+-am ; + +# test weird file names +/lost+found -> +p ; + +# test quoted strings +"/qfoo" -> +p ; + ; + +# simple default policy +/simple -> +ppp; + +# variable +$(poo) = pinug; +/simplevar -> $(poo) ; +$(turd) = /test6; +$(turd) -> $(poo); + +# omit with space seperation +! /omit ; + +# omit with no space separation + !/omit ; + +# named attributes +/namedattr -> +pinug (name1 value1) ; + +# multiple attributes +/namedattr2 -> +pinug (emailreport on; emailsendto genek; name3 val3; name4 val4; name5 val5 ) ; + +# test line continuations +/turd \ + ->\ + +p + ; + +@@END +# the following isn't implemented yet +#########################################3 + +# attributes on specifers +/conditions { + xxx: +pinug (inside1 name1 ;) ; + yyy: +pinug ; + zzz: +pinug ; + default: +pinug ; + }; + + + +# multiple specmasks +/conditions { + xxx: +pinug ; + yyy: +pinug ; + zzz: +pinug ; + default: +pinug ; + }; \ No newline at end of file diff --git a/src/parser/testfiles/poleasy.txt b/src/parser/testfiles/poleasy.txt new file mode 100644 index 0000000..f88a1f6 --- /dev/null +++ b/src/parser/testfiles/poleasy.txt @@ -0,0 +1 @@ +/etc jj ; diff --git a/src/parser/testfiles/polhard.txt b/src/parser/testfiles/polhard.txt new file mode 100644 index 0000000..1586dc2 --- /dev/null +++ b/src/parser/testfiles/polhard.txt @@ -0,0 +1,85 @@ + +# test weird file names +/lost+found -> +p ; +/l-o_st+fo/und -> +ping (l-o_st+fo/und2 l-o_st+fo/und3) ; + +# test variables +$(ReadOnly) = ping; +/simplevar -> $(ReadOnly) ; +/var -> $(ReadOnly)-p ; + +# test line continuations +c:/test -> +p ; + +/turd \ + ->\ + +p + ; + +# test quoted strings +"/qfoo" -> +p ; +"/Program Files" -> +p ; +" /lots o' spaces " -> +p ; +" colon: semicolon; quote' " -> +p ; + +# test attributes +/namedattr2 -> +p ( name1 value1; name2 value2; ) ; +/namedattr -> +p (name1 value1; ) ; + +# test propvector +c:/test -> +p ; + +/test -> +p ; +/test -> +p-p ; +/test -> +pinugs-am ; +/test -> +pinugs---am ; +/test -> +pinugs-+-am ; + + +# attributes and props +/namedattr3 -> +pinug ( name1 value1; name2 value2; ) ; +/namedattr4 -> +pinug (name1 value1; ) ; + +# simple default policy +/simple -> +ppp; + + +# omit with space seperation +! /omit ; + +# omit with no space separation + !/omit ; + +# multiple attributes +/namedattr -> +pinug (emailreport on; emailsendto genek; name3 val3; name4 val4; name5 val5; ) ; + + +@@END +# the following isn't implemented yet +#########################################3 + +# multiple specmasks +/conditions -> { + xxx -> +pinug ; + yyy -> +pinug ; + zzz -> +pinug ; + default -> +pinug ; + }; + +# attributes on specifers +/conditions -> { + xxx -> +pinug (inside1 name1 ;) ; + yyy -> +pinug ; + zzz -> +pinug ; + default -> +pinug ; + }; + + +# hard ones + +/conditions -> { + xxx -> +pinug (inside1 name1 ;) ; + yyy -> $(poo)+pinug ; + zzz -> +pinug ( inside1 name1 ; outside name2); + default -> $(turd)-p ; + }; \ No newline at end of file diff --git a/src/parser/testfiles/polruleattr.txt b/src/parser/testfiles/polruleattr.txt new file mode 100644 index 0000000..468fa36 --- /dev/null +++ b/src/parser/testfiles/polruleattr.txt @@ -0,0 +1,4 @@ +( emailreport on ; ) +{ + /foo -> +pinugs ; +} \ No newline at end of file diff --git a/src/parser/tokens.l b/src/parser/tokens.l new file mode 100644 index 0000000..94bc773 --- /dev/null +++ b/src/parser/tokens.l @@ -0,0 +1,356 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* +/////////////////////////////////////////////////////////////////////////////// +// tokens.l -- describes all the tokens for the policy language +// +*/ + +/* increases number of states in DFA to 5000 */ +%p 5000 + +%{ +#include "stdtwparser.h" + +//#ifndef YYNEWLINE +# include "twparser/yylex.h" +# include "twparser/yyparse.h" +//#endif + +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#include + +#include "core/debug.h" + +#include "policyparser.h" +#include "parserhelper.h" +#include "genreparseinfo.h" +#include "core/stringutil.h" +#include "core/displayencoder.h" + + + +/* specify that the lexer exit on EOF */ +int yywrap() +{ + return 1; +} + +/* wrapper around cDebug tracing */ +void lextrace(const TCHAR*str) +{ + cDebug d("\t\t\t\tlexer"); + d.TraceDetail( _T("%s\n"), str); +} + +// since i've replaced this with a non-va_arg yyerror, +// call this when you hit a syntax error and then call +// the non-va_arg yyerror with the result +std::string FormatSyntaxError( char ch, const char* pszAdditionalMsg = NULL ) +{ + // TODO:BAM MKS will call yyerror with narrow-char hard-coded string, so if + // we do it here as well, I suppose that's OK. This should be eventually + // corrected. + + std::ostringstream ssErr; + ssErr << "Syntax error: \'" << ch << "\'"; + if( pszAdditionalMsg ) + ssErr << ", " << pszAdditionalMsg; + + return ssErr.str(); +} + +// saves typing +#define TRACE_RETURN(x) lextrace(_T(#x)); return x + +%} + +/* Defining a start-condition for parsing a global definitions section */ +/* in a special manner: */ +%x globals + +WS [ \t\r] +COMMENT #.* +BSLASH \\ +DBL_QUOTE \" +DIRECTIVE @@ +EOL \n +SEMICOLON ; +DOLLAR \$ +COMMA \, +PIPE \| +OROR \|\| +EQUALS = + +LPAREN \( +RPAREN \) + + +/* normal strings -- anything but our reserved symbols */ +STRING ([^!\{\}>\(\)\n\r\t \,;=$#|\"]+) + + +/* quoted strings can contain escaped characters (including escaped quotes). Can also be empty string. */ +QSTRING (\"(([^\\\"\n])|(\\.))*\") + +SECTION {WS}*{DIRECTIVE}{WS}*section +IFHOST {WS}*{DIRECTIVE}{WS}*ifhost +ELSE {WS}*{DIRECTIVE}{WS}*else +ENDIF {WS}*{DIRECTIVE}{WS}*endif +ERROR {WS}*{DIRECTIVE}{WS}*error +ECHO {WS}*{DIRECTIVE}{WS}*print +END {WS}*{DIRECTIVE}{WS}*end + +%% + +/* Lexer state-switching code for implementing a "global definitions" section while enforcing */ +/* the limited scope of such a construct. The lexer will catch anything that cannot be */ +/* coerced into a variable definition, and output special warnings. */ + +^{SECTION}{WS}*((global)|(GLOBAL)) { + BEGIN( globals ); + } + +/* Are we done with the definitions section? */ +^{SECTION} { + BEGIN(INITIAL); + return TWP_SECTION; + } + +^{ECHO} { TRACE_RETURN(TWP_ECHO); } + +/* We still need to eat white space, line continuations, and comments... */ +{WS}+ { + lextrace(_T("eating spaces...")); /* eat spaces */ + } +{BSLASH}{EOL} { + cParserHelper::IncrementLineNumber(); + lextrace(_T("eating line continuation...")); /* eat line continuations */ + } +{COMMENT} { + lextrace(_T("eating comment...")); + } + +/* We still need to increment the line #, and pass the two tokens needed to */ +/* do variable definitions: */ + +/* We still need to treat strings the same way, just return a differnt ID. TODO: */ +/* Maybe create some helper functions and get rid of all this repeat code? */ +{STRING} { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::string"); + + // convert LPCSTR to TSTRING + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = cStringUtil::StrToTstr( yytext ); + + d.TraceDetail("--> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + + return TWP_GLOBAL_STRING; + } + +{QSTRING} { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::qstring"); + + // get rid of beginning and trailing quotes + std::string strWithQuotes = yytext; + std::string str = strWithQuotes.substr(1, strWithQuotes.size() - 2); + + // convert any escape characters + TSTRING strW; + cParserUtil::InterpretEscapedString( str, strW ); + + d.TraceDetail(_T("read as --> <%s>\n"), strW.c_str()); + + // convert TSTRING to cParseString + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = strW; + + + d.TraceDetail("interpreted as --> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + return TWP_GLOBAL_STRING; + } + +{SEMICOLON} { TRACE_RETURN(TWP_SEMICOLON); } +{EQUALS} { TRACE_RETURN(TWP_EQUALS); } + +\n { cParserHelper::IncrementLineNumber(); } +. { + std::string strError; + strError = FormatSyntaxError( yytext[0], "The global section only accepts statements of the form:\n variable = value;\n" ); + + // MKS defines yyerror with char*, for some stupid reason, + // so cast it away + yyerror( const_cast( strError.c_str() ) ); + } /* catches anything that cannot be deemed a variable definition and exits. */ + +/* consume spaces */ +{WS}+ { + lextrace(_T("eating spaces...")); /* eat spaces */ + } + +{BSLASH}{EOL} { + cParserHelper::IncrementLineNumber(); + lextrace(_T("eating line continuation...")); /* eat line continuations */ + } + +{COMMENT} { + lextrace(_T("eating comment...")); + } + +"{" { TRACE_RETURN(TWP_LBRACE); } +"}" { TRACE_RETURN(TWP_RBRACE); } + + +"!" { TRACE_RETURN(TWP_BANG); } + +"->" { TRACE_RETURN(TWP_RARROW); } +{EQUALS} { TRACE_RETURN(TWP_EQUALS); } + +{SEMICOLON} { TRACE_RETURN(TWP_SEMICOLON); } +{LPAREN} { TRACE_RETURN(TWP_LPAREN); } +{RPAREN} { TRACE_RETURN(TWP_RPAREN); } +{COMMA} { TRACE_RETURN(TWP_COMMA); } +{PIPE} { TRACE_RETURN(TWP_PIPE); } + + +/* variables */ +{DOLLAR} { TRACE_RETURN(TWP_DOLLAR); } +{OROR} { TRACE_RETURN(TWP_OROR); } + + +^{SECTION} { TRACE_RETURN(TWP_SECTION); } +^{IFHOST} { TRACE_RETURN(TWP_IFHOST); } +^{ELSE} { TRACE_RETURN(TWP_ELSE); } +^{ENDIF} { TRACE_RETURN(TWP_ENDIF); } +^{ERROR} { TRACE_RETURN(TWP_ERROR); } +^{ECHO} { TRACE_RETURN(TWP_ECHO); } +^{END} { lextrace( _T( "@@end" ) ); return 0; } /* logical end of file */ + + +{STRING} { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::string"); + + // convert LPCSTR to TSTRING + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = cStringUtil::StrToTstr( yytext ); + + d.TraceDetail("--> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + + return TWP_STRING; + } + +{QSTRING} { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::qstring"); + + // get rid of beginning and trailing quotes + std::string strWithQuotes = yytext; + std::string str = strWithQuotes.substr(1, strWithQuotes.size() - 2); + + // convert any escape characters + TSTRING strW; + cParserUtil::InterpretEscapedString( str, strW ); + + d.TraceDetail(_T("read as --> <%s>\n"), strW.c_str()); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + cParserHelper::GetGenreInfo()->DoVarSubstitution( strW ); + } + + // convert TSTRING to cParseString + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = strW; + + +#ifdef _DEBUG + TSTRING strDisplay = *mpstring; + cDisplayEncoder e; + e.Encode( strDisplay ); + d.TraceDetail("interpreted as --> <%s>\n", strDisplay.c_str()); +#endif // _DEBUG + + // attach to lval + yylval.mpString = mpstring; + return TWP_STRING; + } + +/* not implemented yet +^{DIRECTIVE}{WS}*include{WS}\"[^\"]\" { + + // get include file name + TCHAR szFilename[iFSServices::TW_MAX_PATH]; + + FILE* fpIncludeFile = _tfopen( szFilename, _T("r") ); + if( fpIncludeFile ) + { + lex_include_file( fpIncludeFile ); + + fclose( fpIncludeFile ); + } + } + */ + +\n { cParserHelper::IncrementLineNumber(); } +. { + std::string strError; + strError = FormatSyntaxError( yytext[0] ); + + // MKS defines yyerror with char*, for some stupid reason, + // so cast it away + yyerror( const_cast( strError.c_str() ) ); + } /* catches anything else that's not in here and quits */ + + +%% + + + diff --git a/src/prime.pl b/src/prime.pl new file mode 100755 index 0000000..d7cb22d --- /dev/null +++ b/src/prime.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl + + %twcfgdirs = ( + + ROOT => '', + POLFILE => 'tw.pol', + DBFILE => 'database.twd', + REPORTFILE => 'report.twr', + SITEKEYFILE => 'site.key', + LOCALKEYFILE => 'local.key', + TEMPDIRECTORY => 'temp/' + + ); + + %twcfgprops = ( + + EDITOR => '/usr/bin/vi', + LATEPROMPTING => 'false', + LOOSEDIRECTORYCHECKING => 'false', + MAILNOVIOLATIONS => 'true', + EMAILREPORTLEVEL => '3', + REPORTLEVEL => '3', + MAILMETHOD => 'SENDMAIL', + SYSLOGREPORTING => 'false', + MAILPROGRAM => '/usr/lib/sendmail -oi -t' + + ); + + +if (scalar(@ARGV) == 0) { + + print "usage: prime rootdir bindir\n"; + exit; +} +else { + + $twcwd = `pwd`; + chomp($twcwd); + chop($twcwd) if $twcwd =~ /\/$/; + + $twrootdir = shift @ARGV; + $bindir = shift @ARGV; + + CreateDefaultConfig(); + GenerateKeys(); + SignConfigFile(); + + system("cd $twrootdir; ln -s ../$bindir/tripwire") if -e "$bindir/tripwire"; + system("cd $twrootdir; ln -s ../$bindir/twadmin") if -e "$bindir/twadmin"; + system("cd $twrootdir; ln -s ../$bindir/twprint") if -e "$bindir/twprint"; + system("cd $twrootdir; ln -s ../$bindir/siggen") if -e "$bindir/siggen"; + +} + +exit; + +###################################################################### +# Create a default config file in the passed +# in directory, and create the appropriate +# directory structure to along with the config +# file... +# +sub CreateDefaultConfig { + + my ($key, $value); + + # make the root and bin directories if not there + # already... + # + mkdir($twrootdir,0755) if !-e $twrootdir; + + open(CFG, ">$twrootdir/twcfg.txt") || die "couldn't open cfg file..."; + + print "generating configuration file...\n"; + + # Output the twcfg.txt file... + # + while (($key, $value) = each(%twcfgdirs)) { + + # cfg file must have full paths, so prepend working directory... + # + printf(CFG "%-28s= %s\n", $key, "$twcwd/$twrootdir/$value"); + + } + + # Output the non directory options to the config file. + # + while (($key, $value) = each(%twcfgprops)) { + + printf(CFG "%-28s= %s\n", $key, $value); + } + + + close(CFG); + +} + +sub GenerateKeys { + + # Don't gen the keys if they are already sitting there... + # + # + if (! (-e "$twrootdir/site.key")) { + print "generating site key...\n"; + $junk = `$bindir/twadmin -m G -S $twrootdir/site.key -Q testing`; + } + + $? && return 0; + + if (! (-e "$twrootdir/local.key")) { + print "generating local key...\n"; + $junk = `$bindir/twadmin -m G -L $twrootdir/local.key -P testing`; + } + + return ($? == 0); +} + + +sub SignConfigFile { + + if (!-e "$twrootdir/tw.cfg") { + print "signing configuration file...\n"; + $junk = `$bindir/twadmin -m F -Q testing -c $twrootdir/tw.cfg -S $twrootdir/site.key $twrootdir/twcfg.txt`; + } + + return ($? == 0); +} diff --git a/src/rmcr.pl b/src/rmcr.pl new file mode 100755 index 0000000..cb564c7 --- /dev/null +++ b/src/rmcr.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w + +# rmcr.pl +# +# remove all "\r\n" sequences. + +if (!$ARGV[0]) { + print <)) + { + $instring =~ s/\r\n/\n/; + $buffer .= $instring; + } + close (IN); + + if (open (OUT, ">$filename")) + { + print OUT $buffer; + close (OUT); + } + else + { + print "Could not open $filename for writing.\n"; + } + } + else + { + print "Could not open $filename for reading.\n"; + } +} + diff --git a/src/siggen/Makefile.am b/src/siggen/Makefile.am new file mode 100644 index 0000000..089cd70 --- /dev/null +++ b/src/siggen/Makefile.am @@ -0,0 +1,17 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 + +INCLUDES = -I.. +LIBS = -ltripwire -lcryptlib @LIBS@ +LDFLAGS = @LDFLAGS@ -L../../lib + +sbin_PROGRAMS = siggen +siggen_SOURCES = \ + siggen.cpp siggencmdline.cpp siggenmain.cpp \ + siggenstrings.cpp stdsiggen.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +CLEANFILES = ../../bin/siggen + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin diff --git a/src/siggen/Makefile.in b/src/siggen/Makefile.in new file mode 100644 index 0000000..52eecdd --- /dev/null +++ b/src/siggen/Makefile.in @@ -0,0 +1,423 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(siggen_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +sbin_PROGRAMS = siggen$(EXEEXT) +subdir = src/siggen +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(sbin_PROGRAMS) +am_siggen_OBJECTS = siggen.$(OBJEXT) siggencmdline.$(OBJEXT) \ + siggenmain.$(OBJEXT) siggenstrings.$(OBJEXT) \ + stdsiggen.$(OBJEXT) +siggen_OBJECTS = $(am_siggen_OBJECTS) +siggen_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(siggen_SOURCES) +DIST_SOURCES = $(siggen_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ -L../../lib +LIBOBJS = @LIBOBJS@ +LIBS = -ltripwire -lcryptlib @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 +INCLUDES = -I.. +siggen_SOURCES = \ + siggen.cpp siggencmdline.cpp siggenmain.cpp \ + siggenstrings.cpp stdsiggen.cpp + +CLEANFILES = ../../bin/siggen +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/siggen/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/siggen/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$f"; \ + done + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +siggen$(EXEEXT): $(siggen_OBJECTS) $(siggen_DEPENDENCIES) + @rm -f siggen$(EXEEXT) + $(CXXLINK) $(siggen_LDFLAGS) $(siggen_OBJECTS) $(siggen_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-sbinPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am uninstall-sbinPROGRAMS + + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/siggen/Script2.aps b/src/siggen/Script2.aps new file mode 100644 index 0000000..2479766 Binary files /dev/null and b/src/siggen/Script2.aps differ diff --git a/src/siggen/resource.h b/src/siggen/resource.h new file mode 100644 index 0000000..5510e67 --- /dev/null +++ b/src/siggen/resource.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script2.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + diff --git a/src/siggen/siggen.cpp b/src/siggen/siggen.cpp new file mode 100644 index 0000000..06b63a8 --- /dev/null +++ b/src/siggen/siggen.cpp @@ -0,0 +1,71 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: siggen.cpp +// Date....: 5/12/99 +// Creator.: Brian McFeely (bmcfeely) +// +// +#include "stdsiggen.h" +#include "siggen.h" + +#include "core/core.h" +#include "db/db.h" +#include "twcrypto/twcrypto.h" +#include "twparser/twparser.h" +#include "tw/tw.h" +#include "fco/fco.h" + + +#include "fs/fs.h" +#include "util/util.h" + +/////////////////////////////////////////////////////////////////////////////// +// cSiggen +/////////////////////////////////////////////////////////////////////////////// + +TSS_ImplementPackage( cSiggen ) + +cSiggen::cSiggen() +{ + TSS_Dependency( cTW ); + TSS_Dependency( cUtil ); + TSS_Dependency( cCore ); + TSS_Dependency( cFCO ); + TSS_Dependency( cFS ); + TSS_Dependency( cDb ); + TSS_Dependency( cTWParser ); + TSS_Dependency( cTWCrypto ); +} + +// eof: siggen.cpp + diff --git a/src/siggen/siggen.h b/src/siggen/siggen.h new file mode 100644 index 0000000..666bec9 --- /dev/null +++ b/src/siggen/siggen.h @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: siggen.h +// Date....: 5/12/99 +// Creator.: Brian McFeely (bmcfeely) +// +// Package initialization class +// + +#ifndef __SIGGEN_H +#define __SIGGEN_H + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include "core/package.h" + + +TSS_BeginPackage( cSiggen ) + + TSS_DECLARE_STRINGTABLE; + +public: + cSiggen(); + +TSS_EndPackage( cSiggen ) + + +#endif//__SIGGEN_H + diff --git a/src/siggen/siggencmdline.cpp b/src/siggen/siggencmdline.cpp new file mode 100644 index 0000000..33be2db --- /dev/null +++ b/src/siggen/siggencmdline.cpp @@ -0,0 +1,381 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//siggencmdline.cpp +#include "stdsiggen.h" +#include "siggencmdline.h" +#include "core/cmdlineparser.h" + +#include "core/archive.h" // cArchive and friends +#include "fco/signature.h" // cSignature +#include "fs/fsstrings.h" // file system related strings +#include "core/usernotify.h" // for notifying the user of events +#include "core/errorbucketimpl.h" // for the error table +#include "core/fsservices.h" +#include "tw/twstrings.h" +#include "core/displayencoder.h" +#include "siggenstrings.h" + +#include // for the FileExists() stuff + + +#if IS_UNIX +#include +#include +#include +#include +//#include +int _getch(void); +#endif + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +// Static Functions, Variables -- +/////////////////////////////////////////////////////////////////////////////// +static void PrintHeader(TSTRING filename); +static bool util_FileExists(const TSTRING &fileName); + +//========================================================================= +// GLOBALS +//========================================================================= + +const TCHAR* g_szEightyDashes = _T("--------------------------------------------------------------------------------"); + +/////////////////////////////////////////////////////////////////////////////// +//Insulated implementation for cSiggenCmdLine +struct cSiggen_i +{ + cSiggen_i() : mPrintHex(false), mTerseOutput(false) {} + ~cSiggen_i(); + + //Data Members: + bool mPrintHex; + //If this is true, the signatures will be output in hex rather than Base64 + bool mTerseOutput; + //If this is true, only the signatures will be printed, and the output will only use one line. + + typedef std::list > ListType; + ListType mSignatures; + std::list mFilesToCheck; + //A list of the files that need signatures generated for them. +}; + +//Dtor: +cSiggen_i::~cSiggen_i() +{ + cSiggen_i::ListType::iterator i; + //Delete all the dynamically allocated signature objects. + for (i = mSignatures.begin(); i != mSignatures.end(); ++i) { + if ( ((*i).first) != NULL) + delete ((*i).first); + } +} + +//############################################################################# +// cSiggenCmdLine +//############################################################################# + +cSiggenCmdLine::cSiggenCmdLine() +{ + mpData = new cSiggen_i; +} + +cSiggenCmdLine::~cSiggenCmdLine() +{ + delete mpData; +} + + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser -- Make the command line cognizant of siggen's arguments +/////////////////////////////////////////////////////////////////////////////// +void cSiggenCmdLine::InitCmdLineParser(cCmdLineParser& parser) +{ + + parser.AddArg(HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_NONE) ; + //Signatures: + parser.AddArg(CRC32, TSTRING(_T("C")), TSTRING(_T("CRC32")), cCmdLineParser::PARAM_NONE); + parser.AddArg(MD5, TSTRING(_T("M")), TSTRING(_T("MD5")), cCmdLineParser::PARAM_NONE); + parser.AddArg(SHA, TSTRING(_T("S")), TSTRING(_T("SHA")), cCmdLineParser::PARAM_NONE); + parser.AddArg(HAVAL, TSTRING(_T("H")), TSTRING(_T("HAVAL")), cCmdLineParser::PARAM_NONE); + + //Output switches + parser.AddArg(ALL, TSTRING(_T("a")), TSTRING(_T("all")), cCmdLineParser::PARAM_NONE); + parser.AddArg(HEX, TSTRING(_T("h")), TSTRING(_T("hexadecimal")), cCmdLineParser::PARAM_NONE); + parser.AddArg(TERSE, TSTRING(_T("t")), TSTRING(_T("terse")), cCmdLineParser::PARAM_NONE); + + //file parameters + parser.AddArg(PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); +} + +int cSiggenCmdLine::Execute() +{ + cFileArchive arch; + //archive for reading in files + TCOUT.flags( ( TCOUT.flags() & ~std::ios::adjustfield ) | std::ios::left ); + //align all output to the left. + int rtn = 0; + // return value -- by default, it is set to 0 (OK) + + //Check to see if files have been specified. + if(mpData->mFilesToCheck.empty()) + return 0; + + //Iterate over file list and generate each signature: + std::list::iterator fileIter; + for (fileIter = mpData->mFilesToCheck.begin(); fileIter != mpData->mFilesToCheck.end(); ++fileIter) + { + cDisplayEncoder e; + TSTRING displayStr = *fileIter; + e.Encode(displayStr); + + if(!mpData->mTerseOutput) + PrintHeader( displayStr ); + + if( ! util_FileExists( *fileIter ) ) + { + TCOUT << TSS_GetString( cSiggen, siggen::STR_ERR_NO_FILE ) << _T(": ") << displayStr.c_str() <Stat(*fileIter, fileInfo); + if(fileInfo.mFileType != cFSStatArgs::TY_FILE) + { + // Not a regular file; warn and skip this file. + // + TCOUT << displayStr << TSS_GetString( cSiggen, siggen::STR_SIGGEN_NOT_REG_FILE ) << std::endl; + rtn = 1; + continue; + } + } + catch(eFSServices& e) + { + cErrorReporter::PrintErrorMsg(e); + rtn = 1; + continue; + } + + //Prepare the archive for reading from current file (in loop). + try + { + arch.OpenRead( (*fileIter).c_str() ); + } + catch (eArchive&) + { + TCOUT << TSS_GetString( cSiggen, siggen::STR_ERR_OPEN_FAILED ) << _T(": ") << displayStr.c_str() < list and add each signature to the + // sig generator + // + cArchiveSigGen asg; + std::list< std::pair >::iterator sigIter; + for ( sigIter = mpData->mSignatures.begin(); sigIter!= mpData->mSignatures.end(); ++sigIter ) + asg.AddSig( (*sigIter).first ); + + // + // calculate signatures + // + arch.Seek(0, cBidirArchive::BEGINNING); + asg.CalculateSignatures( arch ); + arch.Close(); + + // + // Iterate over the list and output each signature: + // + for ( sigIter = mpData->mSignatures.begin(); sigIter != mpData->mSignatures.end(); ++sigIter ) + { + if(!mpData->mTerseOutput) + TCOUT.width(20); + + //Set the output string to Hex or Base64, depending on the value of mPrintHex + TSTRING sigStringOut; + if (mpData->mPrintHex) + sigStringOut = ((*sigIter).first)->AsStringHex(); + else + sigStringOut = ((*sigIter).first)->AsString(); + + //Output the signatures, include identifiers and newlines only if mTerseOutput is false. + if(!mpData->mTerseOutput) + TCOUT << (*sigIter).second.c_str(); + + TCOUT << sigStringOut; + + if(!mpData->mTerseOutput) + TCOUT << endl; + else + TCOUT << _T(" "); + //Output finished for iteration + + }//end for + + + //Seperate lines of signatures (for multiple files) with a newline (if terse output) + if(mpData->mTerseOutput) + TCOUT << endl; + } + + if(!mpData->mTerseOutput) + TCOUT << g_szEightyDashes << _T("\n"); + + return rtn; +} + +//Interprets the parsed command line and sets the member variables necessary for correct output. +//See cSiggen_i. +//Returns 0 if no file parameters have been passed, otherwise, returns 1. +int cSiggenCmdLine::Init(cCmdLineParser& parser) +{ + cCmdLineIter iter(parser); //iterator for traversing command line + iter.SeekBegin(); + int i = 0; //loop variable + bool crc_select = false, md5_select = false, sha_select = false, haval_select = false; + //boolean locals for dealing with ALL switch. (temp.?) fix -DA + bool switch_present = false; + int ret = 0; //return value. will be false unless some file is specified. + + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case HELP: + { + return 0; + break; + } + case CRC32: + { + crc_select = switch_present = true; + break; + } + case MD5: + { + md5_select = switch_present = true; + break; + } + case SHA: + { + sha_select = switch_present = true; + break; + } + case HAVAL: + { + haval_select = switch_present = true; + break; + } + case ALL: + { + crc_select = md5_select = sha_select = haval_select = switch_present = true; + break; + } + case HEX: + { + mpData->mPrintHex = true; + break; + } + case TERSE: + { + mpData->mTerseOutput = true; + break; + } + case PARAMS: + { + ret |= 1; + for (; i < iter.NumParams(); ++i) { + mpData->mFilesToCheck.push_back(TSTRING (iter.ParamAt(i)) ); + } + } + default: + break; + } + } + + //Default behavior is to print all signatures if no switch is specified. + if(!switch_present) + crc_select = md5_select = sha_select = haval_select = true; + + //Push the signatures and their output identifiers onto the mSignature list: + if(crc_select) + { + iSignature* sig_ptr = new cCRC32Signature; + TSTRING str = TSS_GetString( cFS, fs::STR_PROP_CRC32); + mpData->mSignatures.push_back(std::pair< iSignature*, TSTRING>(sig_ptr, str)); + } + if(md5_select) + { + iSignature* sig_ptr = new cMD5Signature; + TSTRING str = TSS_GetString( cFS, fs::STR_PROP_MD5); + mpData->mSignatures.push_back(std::pair< iSignature*, TSTRING>(sig_ptr, str)); + } + if(sha_select) + { + iSignature* sig_ptr = new cSHASignature; + TSTRING str = TSS_GetString( cFS, fs::STR_PROP_SHA); + mpData->mSignatures.push_back(std::pair< iSignature*, TSTRING>(sig_ptr, str)); + } + if(haval_select) + { + iSignature* sig_ptr = new cHAVALSignature; + TSTRING str = TSS_GetString( cFS, fs::STR_PROP_HAVAL); + mpData->mSignatures.push_back(std::pair< iSignature*, TSTRING>(sig_ptr, str)); + } + + return ret; +} + +//Prints a header for each signature. +void PrintHeader( TSTRING filename) +{ + TCOUT << g_szEightyDashes << _T( "\n" ); + TCOUT << _T("Signatures for file: ") << filename.c_str() << _T("\n\n"); +} + +bool util_FileExists(const TSTRING& fileName) +{ +#if IS_UNIX + // for unix we may be able to use the same logic as above, but + // it is too close to 2.2.1 release to make that change w/o testing. + // I know the above works for windows. + return _taccess(fileName.c_str(), F_OK) == 0; +#endif +} + diff --git a/src/siggen/siggencmdline.h b/src/siggen/siggencmdline.h new file mode 100644 index 0000000..3984f80 --- /dev/null +++ b/src/siggen/siggencmdline.h @@ -0,0 +1,87 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// siggencmdline.h + +#ifndef __SIGGENCMDLINE_H +#define __SIGGENCMDLINE_H + +//Forward Declarations: +class cCmdLineParser; +class cErrorBucket; +class cArchive; + +//Struct for storing class data. +struct cSiggen_i; + +class cSiggenCmdLine { +public: + public: + cSiggenCmdLine(); + ~cSiggenCmdLine(); + + void InitCmdLineParser (cCmdLineParser& parser ); + // call this to initialize the command line parser + + int Init ( cCmdLineParser& parser ); + //This function should be called prior to Execute. + //It's purpose is to transfer the information from the + //cmdlineparser class to the member data struct. + int Execute (); + //This is where the actual execution will take place. + + // constants for all the command line arguments + enum CmdLineArgs + { + HELP, + //signatures + CRC32, + MD5, + SHA, + HAVAL, + + //Output switches: + ALL, + HEX, + TERSE, + + PARAMS, // the final parameters + + NUM_CMDLINEARGS + }; + + private: + cSiggen_i* mpData; + //insulated implementation. +}; + +#endif //__SIGGENCMDLINE_H + diff --git a/src/siggen/siggenmain.cpp b/src/siggen/siggenmain.cpp new file mode 100644 index 0000000..7d70845 --- /dev/null +++ b/src/siggen/siggenmain.cpp @@ -0,0 +1,201 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// siggenmain.cpp +#include "stdsiggen.h" + + + +#include "core/types.h" +#include "core/tchar.h" +#include "core/debug.h" +#include "core/error.h" + +#include "siggencmdline.h" +#include "core/cmdlineparser.h" +#include "core/errorbucketimpl.h" +#include "core/usernotifystdout.h" +#include "core/timebomb.h" +#include "fs/fsstrings.h" +#include "tw/twstrings.h" +#include "tw/twutil.h" // for cTWUtil::PrintErrorMsg +#include "siggenstrings.h" + +#include "siggen.h" + +#include +#include +#include + +#if IS_UNIX +#include "core/unixfsservices.h" +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +// terminate and unexpected handlers +// TODO: move these to a common library +/////////////////////////////////////////////////////////////////////////////// +void tw_terminate_handler() +{ + fputs("### Internal Error.\n### Terminate Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +void tw_unexpected_handler() +{ + fputs("### Internal Error.\n### Unexpected Exception Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +static void SiggenInit() +{ + TSS_Dependency( cSiggen ); + + static cUserNotifyStdout unStdout; + static cErrorTracer et; + static cErrorReporter er; + + // + // initialize iUserNotify + // + iUserNotify::SetInstance( &unStdout ); + iUserNotify::GetInstance()->SetVerboseLevel(iUserNotify::V_NORMAL); + + // + // set up the file system services + // +#if IS_UNIX + static cUnixFSServices fss; +#endif + iFSServices::SetInstance( &fss ); + + + // + // set up an error bucket that will spit things to stderr + // + et.SetChild( &er ); + +} + +int __cdecl _tmain(int argc, const TCHAR** argv) +{ + int ret = 0; + + if (TimeBombExploded()) + return 1; + + try + { + // set unexpected and terminate handlers + // Note: we do this before Init() in case it attempts to call these handlers + // TODO: move this into the Init() routine + EXCEPTION_NAMESPACE set_terminate(tw_terminate_handler); + EXCEPTION_NAMESPACE set_unexpected(tw_unexpected_handler); + + //cTWInit twInit( argv[0] ); + SiggenInit(); + + cDebug::SetDebugLevel(cDebug::D_DETAIL); + cSiggenCmdLine siggen; + + // first, process the command line + if (argc < 2) + { + TCOUT << TSS_GetString( cSiggen, siggen::STR_SIGGEN_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + + ret = 1; + goto exit; + } + + // + // Display the version info... + // this is quick and dirty ... just the way I like it :-) -- mdb + // + if (_tcscmp(argv[1], _T("--version")) == 0) + { + TCOUT << TSS_GetString( cTW, tw::STR_VERSION_LONG) << std::endl; + ret=0; + goto exit; + } + + + cCmdLineParser cmdLine; + siggen.InitCmdLineParser(cmdLine); + try + { + cmdLine.Parse(argc, argv); + } + catch( eError& e ) + { + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + + ret = 1; + goto exit; + } + + cCmdLineIter iter(cmdLine); + if (iter.SeekToArg(cSiggenCmdLine::HELP)) + { + TCOUT << TSS_GetString( cSiggen, siggen::STR_SIGGEN_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString( cSiggen, siggen::STR_SIGGEN_USAGE) << std::endl; + ret = 1; + goto exit; + } + + if(! siggen.Init(cmdLine)) + { + TCOUT << TSS_GetString( cSiggen, siggen::STR_SIGGEN_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString( cSiggen, siggen::STR_SIGGEN_USAGE) << std::endl; + ret = 1; + goto exit; + } + ret = siggen.Execute(); + + }//end try block + + catch (eError& error) + { + cErrorReporter::PrintErrorMsg(error); + ASSERT(false); + } + +exit: + + + return ret; +}//end MAIN + diff --git a/src/siggen/siggenstrings.cpp b/src/siggen/siggenstrings.cpp new file mode 100644 index 0000000..a886c9a --- /dev/null +++ b/src/siggen/siggenstrings.cpp @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: siggenstrings.cpp +// Date....: 5/12/99 +// Creator.: Brian McFeely (bmcfeely) +// + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "stdsiggen.h" +#include "siggenstrings.h" + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// String Table +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +TSS_BeginStringtable( cSiggen ) + + TSS_StringEntry( siggen::STR_SIGGEN_USAGE, + _T("Usage: siggen [options] file1 [file2...]\n") + _T("\n") + _T(" -t --terse\n") + _T(" -h --hexadecimal\n") + _T(" -a --all\n") + _T(" -C --CRC32\n") + _T(" -M --MD5\n") + _T(" -S --SHA\n") + _T(" -H --HAVAL\n") + _T("file1 [file 2 ...]\n") + _T("\n") + ), + TSS_StringEntry( siggen::STR_SIGGEN_VERSION, _T("siggen: Display signature function values. \n")), + TSS_StringEntry( siggen::STR_ERR_OPEN_FAILED, _T("File could not be opened") ), + TSS_StringEntry( siggen::STR_ERR_NO_FILE, _T("File does not exist") ), + TSS_StringEntry( siggen::STR_SIGGEN_NOT_REG_FILE, _T(" is not a regular file; ignoring.") ) + +TSS_EndStringtable( cSiggen ) + +// eof: siggenstrings.cpp + diff --git a/src/siggen/siggenstrings.h b/src/siggen/siggenstrings.h new file mode 100644 index 0000000..ca1a570 --- /dev/null +++ b/src/siggen/siggenstrings.h @@ -0,0 +1,56 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: siggenstrings.h +// Date....: 5/12/99 +// Creator.: Brian McFeely (bmcfeely) +// +// Package string class +// + +#ifndef __SIGGENSTRINGS_H +#define __SIGGENSTRINGS_H + +#include "siggen.h" + +TSS_BeginStringIds( siggen ) + + STR_SIGGEN_USAGE, + STR_SIGGEN_VERSION, + STR_SIGGEN_NOT_REG_FILE, + STR_ERR_NO_FILE, + STR_ERR_OPEN_FAILED + +TSS_EndStringIds( siggen ) + +#endif // __SIGGENSTRINGS_H + diff --git a/src/siggen/stdsiggen.cpp b/src/siggen/stdsiggen.cpp new file mode 100644 index 0000000..54e47e1 --- /dev/null +++ b/src/siggen/stdsiggen.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdsiggen.cpp +// Date....: 5/12/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdsiggen.h" + +// eof: stdsiggen.cpp diff --git a/src/siggen/stdsiggen.h b/src/siggen/stdsiggen.h new file mode 100644 index 0000000..874dc91 --- /dev/null +++ b/src/siggen/stdsiggen.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdsiggen.h +// +// Standard includes for the siggen project. +// + +#include "core/stdcore.h" + diff --git a/src/test-harness/tests/complex.pm b/src/test-harness/tests/complex.pm new file mode 100644 index 0000000..201f9f0 --- /dev/null +++ b/src/test-harness/tests/complex.pm @@ -0,0 +1,166 @@ + +use twtools; + +package complex; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-createDir" => { + + # An add violation for adding blah.txt, + # and a change violation for changing the + # contents of the directory proper. + # + changeFunc => \&twtools::CreateFile, + createFunc => \&twtools::CreateDir, + file => "blah.txt", + dir => "temp", + perms => "a+w", + contents => "testing", + violations => "V:2 S:0 A:1 R:0 C:1" + }, + + "1-createFile" => { + + changeFunc => undef, + createFunc => \&twtools::CreateFile, + file => "test.txt", + dir => "temp", + perms => "a+w", + contents => "testing", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "2-createDir" => { + + changeFunc => undef, + createFunc => \&twtools::CreateDir, + dir => "temp/dog", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "3-createDir" => { + + changeFunc => undef, + createFunc => \&twtools::CreateDir, + dir => "temp/cat", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + # Shouldn't get any violation for creating this + # file since we put a stop rule on temp/dog. + # + "4-createFile" => { + + changeFunc => \&twtools::Chmod, + createFunc => \&twtools::CreateFile, + dir => "temp/dog", + file => "test.txt", + perms => "a+r", + contents => "testing", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + # One change violation for the directory temp/cat, and + # one change violation for the file test.txt itself. + # + "5-createFile" => { + + changeFunc => \&twtools::Chmod, + createFunc => \&twtools::CreateFile, + dir => "temp/cat", + file => "test.txt", + perms => "a+r", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + ); + + + $description = "nested policy test"; + +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < \$(ReadOnly); + + (rulename=level2) + { + $twtools::twcwd/$twtools::twrootdir/$TESTS{"0-createDir"}{dir} -> \$(ReadOnly) (recurse=true); + !$twtools::twcwd/$twtools::twrootdir/$TESTS{"2-createDir"}{dir}; + } + +} + +EOT + +} + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/crc32.pm b/src/test-harness/tests/crc32.pm new file mode 100644 index 0000000..28a071a --- /dev/null +++ b/src/test-harness/tests/crc32.pm @@ -0,0 +1,73 @@ + +use twtools; + +package crc32; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + $description = "crc32 hash check"; +} + + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + twtools::CreateFile( { file => "test", contents => "deadbeef"x5000} ); +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + + # lets see if the system 'cksum' agree's with siggen's md5 hash + # + my ($crc32, undef) = split(/ /, `cksum $twtools::twrootdir/test`); + my $siggen = `$twtools::twrootdir/bin/siggen -h -t -C $twtools::twrootdir/test`; + + chomp $md5sum; + chomp $siggen; + + # cksum issues results in decimal, so get siggen's result in base10. + $siggen = hex($siggen); + + twtools::logStatus(" cksum reports: $crc32\n"); + twtools::logStatus("siggen reports: $siggen\n"); + + $twpassed = $crc32 == $siggen; + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/dbupdate.pm b/src/test-harness/tests/dbupdate.pm new file mode 100644 index 0000000..9b0c448 --- /dev/null +++ b/src/test-harness/tests/dbupdate.pm @@ -0,0 +1,319 @@ + +use twtools; + +package dbupdate; + + +###################################################################### +# One time module initialization goes in here... +# +BEGIN +{ + + # This is the root directory we will be integrity checking + # + $root = "$twtools::twcwd/$twtools::twrootdir/dbupdate-test"; + + # Here are the names of the report files this test will create + # + $report1 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-1.twr"; + $report2 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-2.twr"; + $report3 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-3.twr"; + $report4 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-4.twr"; +} + +###################################################################### +# PolicyFileString -- return the policy text as a string +# +sub PolicyFileString +{ + return < \$(ReadOnly)+M; #read only plus MD5 + +POLICY_END + +} + +###################################################################### +# CreateFile -- create a file with the specified contents +# +# input: path -- path to the file; relative to $root +# contents -- string to put in the file +# +sub CreateFile +{ + my ($path, $contents) = @_; + + system( "echo $contents > $root/$path" ); + + $? && die "Create file failed for $root/$path\n"; +} + +###################################################################### +# RemoveFile -- removes the named file +# +sub RemoveFile +{ + my ($path) = @_; + + if( -e "$root/$path" ) + { + system( "rm -f $root/$path" ); + } + + $? && die "Remove file failed for $root/$path\n"; +} + + +###################################################################### +# CreateDir -- create a directory +# +sub CreateDir +{ + my($dir) = @_; + + # NOTE: mkdir fails if it is already a directory! + # + if( ! -d "$root/$dir" ) + { + system( "rm -f $root/$dir" ); + system( "mkdir -p $root/$dir" ); + + $? && die "Mkdir failed for $root/$dir\n"; + } +} + +###################################################################### +# MoveFile -- move a file from one place to another +# NOTE: file names are relative to $root +# +# input: old_name -- name of file to move +# new_name -- where it should be moved to +# +sub MoveFile +{ + my($old, $new) = @_; + + system( "mv $root/$old $root/$new" ); + $? && die "mv $root/$old $root/$new failed!\n"; +} + +###################################################################### +# PrintDatabase +# +sub PrintDatabase +{ + system( "$twtools::twrootdir/bin/twprint -m d -c $twtools::twrootdir/tw.cfg" ); +} + +###################################################################### +# PrintReport +# +sub PrintReport +{ + my ($report) = @_; + system( "$twtools::twrootdir/bin/twprint -m r -c $twtools::twrootdir/tw.cfg -r $report" ); +} + +###################################################################### +# PrepareForTest -- creates the files that each test will be +# integrity checking and initializes the database. +# +sub PrepareForTest +{ + # make sure we are cleaned up... + # + cleanup(); + + # Make the files we will be using... + # + CreateDir ( "dog" ); + CreateFile( "dog/bark.txt", "bark bark" ); + CreateFile( "meow.txt", "meow" ); + + # Initialize the database + # + twtools::initializeDatabase(); +} + +###################################################################### +# RunBasicTest -- performs a rudimentary UpdateDatabase test +# +sub RunBasicTest +{ + PrepareForTest(); + + printf("%-30s", "-- dbupdate.basic test"); + + # make some violations... + # + MoveFile ( "meow.txt", "cat.txt" ); + CreateFile( "dog/bark.txt", "bark bark bark" ); + + # run the integrity check... + # + twtools::runIntegrityCheck(); + + # Make sure we got 4 violations: 2 mod, 1 add, 1 rm. + # + my ($n, $a, $r, $c) = + twtools::analyzeReport( twtools::runReport() ); + + if( ($n != 4) || ($a != 1) || ($r != 1) || ($c != 2) ) + { + print "FAILED -- initial integrity check was wack!"; + return 0; + } + + # do the database update... + # + twtools::updateDatabase(); + + # do another IC and make sure there are no violations + # + twtools::runIntegrityCheck(); + + ($n, $a, $r, $c) = + twtools::analyzeReport( twtools::runReport() ); + + if( $n != 0 ) + { + print "FAILED -- violations after update!"; + return 0; + } + + print "PASSED!!!\n"; + return 1; +} + +###################################################################### +# RunSecureModeTest -- test that secure-mode high and low are working +# +sub RunSecureModeTest +{ + PrepareForTest(); + + printf("%-30s", "-- dbupdate.secure-mode test"); + + # make a violation and generate a report + # + CreateFile( "dog/bark.txt", "bark bark bark" ); + twtools::runIntegrityCheck( { report => $report1 } ); + + # change the same file in a slightly different way and generate + # another report + # + CreateFile( "dog/bark.txt", "bark bark bark woof" ); + twtools::runIntegrityCheck( { report => $report2 } ); + + # Remove a file and generate a third report + # + RemoveFile( "dog/bark.txt" ); + twtools::runIntegrityCheck( { report => $report3 } ); + + # Add a file and generate the fourth report + # + CreateFile( "dog/cow.txt", "moo moo" ); + twtools::runIntegrityCheck( { report => $report4 } ); + + + # Update the database with report 1. + # + twtools::updateDatabase( { report => $report1 } ); + + # Try to update the database with report 2 ... this should fail + # in secure-mode == high because the "old" values don't match. + # + if( twtools::updateDatabase( + { report => $report2, secure-mode => "high" } ) ) + { + print "FAILED ... Secure-mode high didn't catch a bad update!"; + return 0; + } + + # do a high severity update with report3 -- this should + # succeed + # + if( ! twtools::updateDatabase( + { report => $report3, secure-mode => "high" } ) ) + { + print "FAILED ... Update with report 3 failed!"; + return 0; + } + + # Try 2 again ... now we are trying to update an object that + # doesn't exist in the database at all. This should + # succeed in low but fail in high. + # + if( twtools::updateDatabase( + { report => $report2, secure-mode => "high" } ) ) + { + print "FAILED ... Update with report 2 after 3 succeeded in high mode!"; + return 0; + } + + if( ! twtools::updateDatabase( + { report => $report2, secure-mode => "low" } ) ) + { + print "FAILED ... Update with report 2 after 3 failed in low mode!"; + return 0; + } + + + + print "PASSED!!!\n"; + return 1; +} + + +###################################################################### +# +# Initialize the test +# + +sub initialize +{ + # Make the policy file + # + twtools::generatePolicyFile( PolicyFileString() ); +} + + +###################################################################### +# +# Run the test. +# +sub run +{ + RunBasicTest() || return; + RunSecureModeTest() || return; +} + +sub cleanup +{ + # remove all of the files we were integrity checking... + # + system( "rm -rf $root/*" ); + $? && print "WARNING: dbupdate cleanup failed.\n"; + + # remove the report files we created... + # + system( "rm -f $report1" ) if (-e $report1); + system( "rm -r $report2" ) if (-e $report2); + system( "rm -r $report3" ) if (-e $report3); + system( "rm -r $report4" ) if (-e $report4); + +} + + +###################################################################### +# One time module cleanup goes in here... +# +END +{ +} + +1; + diff --git a/src/test-harness/tests/dirs.pm b/src/test-harness/tests/dirs.pm new file mode 100644 index 0000000..b714b7d --- /dev/null +++ b/src/test-harness/tests/dirs.pm @@ -0,0 +1,155 @@ + +use twtools; + +package dirs; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-createTempDir" => { + + changeFunc => undef, + createFunc => \&twtools::CreateDir, + dir => "temp", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "1-createChildDir" => { + + changeFunc => undef, + createFunc => \&twtools::CreateDir, + dir => "temp/cat", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "2-createChildDir" => { + + changeFunc => undef, + createFunc => \&twtools::CreateDir, + dir => "temp/cat/gray", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "3-createFile" => { + + # this one will cause an add (file added) AND change + # (contents of temp changed) violation. + + changeFunc => \&twtools::CreateFile, + createFunc => undef, + file => "file.txt", + dir => "temp", + perms => "a+w", + contents => "testing", + violations => "V:2 S:0 A:1 R:0 C:1" + }, + + "4-createFile" => { + + # this one will cause a changed violation, since recurse + # is set to 1... + + changeFunc => \&twtools::CreateFile, + createFunc => undef, + file => "file.txt", + dir => "temp/cat", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "5-createFile" => { + + # we are below the recurse level here, so no + # violation for doing whatever... + # + changeFunc => \&twtools::CreateFile, + createFunc => undef, + file => "file.txt", + dir => "temp/cat/gray", + perms => "a+w", + contents => "testing", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + ); + + + $description = "directory (recurse) test"; +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < \$(ReadOnly)(recurse = 1); + +EOT + +} + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + + # this test requires a clean start of it's tree + # + system("rm -rf $twtools::twrootdir/" . $TESTS{"0-createTempDir"}{dir}); +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/hashes.pm b/src/test-harness/tests/hashes.pm new file mode 100644 index 0000000..e9741bc --- /dev/null +++ b/src/test-harness/tests/hashes.pm @@ -0,0 +1,143 @@ + +use twtools; + +package hashes; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-createFile" => { + + changeFunc => \&twtools::MakeBigger, + createFunc => \&twtools::CreateFile, + file => "crc32.txt", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "1-createFile" => { + + changeFunc => \&twtools::MakeBigger, + createFunc => \&twtools::CreateFile, + file => "md5.txt", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "2-createFile" => { + + changeFunc => \&twtools::MakeBigger, + createFunc => \&twtools::CreateFile, + file => "sha.txt", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "3-createFile" => { + + changeFunc => \&twtools::MakeSmaller, + createFunc => \&twtools::CreateFile, + file => "haval.txt", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "4-createFile" => { + + # just a little trickery here -- the changeFunc + # re-creates the file with the same contents, + # so the hashes shouldn't change, although things + # like timestamps will... + # + changeFunc => \&twtools::CreateFile, + createFunc => \&twtools::CreateFile, + file => "cmsh.txt", + perms => "a+w", + contents => "testing", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + + ); + + + $description = "hashes (CMSH) test"; +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < +C; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"1-createFile"}{file} -> +M; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"2-createFile"}{file} -> +S; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"3-createFile"}{file} -> +H; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"4-createFile"}{file} -> +CMSH; + +EOT + +} + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/inoderef.pm b/src/test-harness/tests/inoderef.pm new file mode 100644 index 0000000..8711179 --- /dev/null +++ b/src/test-harness/tests/inoderef.pm @@ -0,0 +1,124 @@ + +use twtools; + +package inoderef; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-createTarget" => { + + changeFunc => undef, + createFunc => \&twtools::CreateFile, + file => "parent.txt", + perms => "a+w", + contents => "testing", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "1-hardlink" => { + + changeFunc => undef, + createFunc => \&twtools::CreateHardLink, + file => "child1.txt", + target => "parent.txt", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "2-hardlink" => { + + changeFunc => \&twtools::RemoveFile, + createFunc => \&twtools::CreateHardLink, + file => "child2.txt", + target => "parent.txt", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "3-hardlink" => { + + changeFunc => \&twtools::RemoveFile, + createFunc => \&twtools::CreateHardLink, + file => "child3.txt", + target => "child1.txt", + perms => "a+w", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + ); + + + $description = "inode count (link) test"; +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < +n; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"1-hardlink"}{file} -> -n; + +EOT + +} + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/md5sum.pm b/src/test-harness/tests/md5sum.pm new file mode 100644 index 0000000..0a37a00 --- /dev/null +++ b/src/test-harness/tests/md5sum.pm @@ -0,0 +1,70 @@ + +use twtools; + +package md5sum; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + $description = "md5 hash check"; +} + + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + twtools::CreateFile( { file => "test", contents => "deadbeef"x5000} ); +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + + # lets see if the system 'md5sum' agree's with siggen's md5 hash + # + my ($md5sum, undef) = split(/ /, `md5sum $twtools::twrootdir/test`); + my $siggen = `$twtools::twrootdir/bin/siggen -h -t -M $twtools::twrootdir/test`; + + chomp $md5sum; + chomp $siggen; + + twtools::logStatus("md5sum reports: $md5sum\n"); + twtools::logStatus("siggen reports: $siggen\n"); + + $twpassed = $md5sum == $siggen; + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/readonly.pm b/src/test-harness/tests/readonly.pm new file mode 100644 index 0000000..230e462 --- /dev/null +++ b/src/test-harness/tests/readonly.pm @@ -0,0 +1,121 @@ + +use twtools; + +package readonly; + + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-permsChange" => { + + changeFunc => \&twtools::Chmod, + createFunc => \&twtools::CreateFile, + file => "readonly.txt", + perms => "a+r-w", + contents => "testing...", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "1-accessed" => { + + changeFunc => \&twtools::Access, + createFunc => \&twtools::CreateFile, + file => "accessed.txt", + perms => "a+r-w", + contents => "testing...", + violations => "V:0 S:0 A:0 R:0 C:0" + }, + + "2-removed" => { + + changeFunc => \&twtools::RemoveFile, + createFunc => \&twtools::CreateFile, + file => "removed.txt", + perms => "a+r-w", + contents => "testing", + violations => "V:1 S:0 A:0 R:1 C:0" + } + + ); + + + $description = "readonly test"; +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < \$(ReadOnly); +$twtools::twcwd/$twtools::twrootdir/$TESTS{"1-accessed"}{file} -> \$(ReadOnly); +$twtools::twcwd/$twtools::twrootdir/$TESTS{"2-removed"}{file} -> \$(ReadOnly); + +EOT + +} + + +###################################################################### +# +# Initialize, get ready to run this test... +# + +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("\n\n*** Beginning $description\n"); + + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + return 0; + } + else { + print "*FAILED*\n"; + ++$twtools::twfailedtests; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; + diff --git a/src/test-harness/tests/sizes.pm b/src/test-harness/tests/sizes.pm new file mode 100644 index 0000000..dac2594 --- /dev/null +++ b/src/test-harness/tests/sizes.pm @@ -0,0 +1,115 @@ + +use twtools; + +package sizes; + +###################################################################### +# One time module initialization goes in here... +# +BEGIN { + + %TESTS = ( + + "0-getsBigger" => { + + changeFunc => \&twtools::MakeBigger, + createFunc => \&twtools::CreateFile, + file => "getsbigger.txt", + perms => "a+w", + contents => "test", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "1-getsSmaller" => { + + changeFunc => \&twtools::MakeSmaller, + createFunc => \&twtools::CreateFile, + file => "getssmaller.txt", + perms => "a+w", + contents => "test", + violations => "V:1 S:0 A:0 R:0 C:1" + }, + + "2-okayToGrow" => { + + changeFunc => \&twtools::MakeBigger, + createFunc => \&twtools::CreateFile, + file => "okaytogrow.txt", + perms => "a+w", + contents => "test", + violations => "V:0 S:0 A:0 R:0 C:0" + } + + ); + + + $description = "file sizes test"; +} + + +###################################################################### +# Return the policy file text for this test... +# +sub getPolicyFileString { + + return < +s; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"1-getsSmaller"}{file} -> +s; +$twtools::twcwd/$twtools::twrootdir/$TESTS{"2-okayToGrow"}{file} -> +l; + +EOT + +} + +###################################################################### +# +# Initialize, get ready to run this test... +# +sub initialize() { + + my $twstr = getPolicyFileString(); + twtools::GeneratePolicyFile($twstr); + +} + + +###################################################################### +# +# Run the test. +# +sub run() { + + my $twpassed = 1; + + twtools::logStatus("*** Beginning $description\n"); + printf("%-30s", "-- $description"); + + ######################################################### + # + # Run the tests describe above in the %TESTS structure. + # + $twpassed = twtools::RunIntegrityTests(%TESTS); + + + ######################################################### + # + # See if the tests all succeeded... + # + if ($twpassed) { + print "PASSED\n"; + } + else { + ++$twtools::twfailedtests; + print "*FAILED*\n"; + } +} + + +###################################################################### +# One time module cleanup goes in here... +# +END { +} + +1; diff --git a/src/test-harness/tests/twtools-api.txt b/src/test-harness/tests/twtools-api.txt new file mode 100644 index 0000000..21f355e --- /dev/null +++ b/src/test-harness/tests/twtools-api.txt @@ -0,0 +1,160 @@ + +Introduction +============ + + +All of these functions take a hash (map), and expect certain keys to +be there. For instance, createDir() expects 'dir' to be a key in the +hash, and it's value is the name of the directory to create. + +Note that you can create anonymous hashes quite easily in order to +call these functions: + + CreateDir( { dir => "$twrootdir/temp"} ); + +Another example is createHardLink(), which expects: + + CreateHardLink( { target => "parent.txt", file => "child.txt" } ); + + +Note that files and directories are _ALWAYS_ created relative to +$twtools::twrootdir. + + +API +=== + +CreateDir(%); + + Creates the directory named by the 'dir' key in the passed in + hash. Note it uses "system("mkdir -p")" to do the work, so it + will create all intermediate directories as well (the -p). + + Example: + + CreateDir( { dir => "temp"} ); + + + +MakeBigger(%); + + Expects the key 'file' to name the file make larger. It + increases the size simply by appending the file name to the + end of the file. If the key 'dir' exists, it is prepended to + the file path. + + Example: + + MakeBigger( { file => "bigger.txt" } ); + MakeBigger( { file => "bigger.txt", dir => "temp" } ); + +MakeSmaller(%); + + + Expects the key 'file' to name the file make smaller. It + decreases the size simply by echoing nothing into the file, + i.e. the size is guarenteed to be 0 afterwards. If the key + 'dir' exists, it is prepended to the file path. + + Example: + + MakeSmaller( { file => "smaller.txt" } ); + MakeSmaller( { file => "smaller.txt", dir => "temp"} ); + + +RemoveFile(%); + + + Expects the key 'file' to name the file to remove. The file is + removed forcibly ("rm -rf"). If the key 'dir' exists, it is + prepended to the file path. + + Example: + + RemoveFile( { file => "byebye.txt" } ); + RemoveFile( { file => "byebye.txt", dir => "temp"} ); + + +Chmod(%); + + Expects the key 'file' for the file name, and 'perms' for the + new permissions. Uses "system("chmod")" to do it's work, not + the built in perl chmod function. If the key 'dir' exists, it + is prepended to the file path. + + Example: + + Chmod( { file => "change.txt", perms => "a+r-w" } ); + Chmod( { file => "change.txt", dir => "temp", perms => "a+r-w" } ); + + +CreateHardLink(%); + + Expects the keys 'target' and 'file', and uses "system("ln + -f")" to do it's work. + + Example: + + CreateHardLink( { target => "parent.txt", file => "child.txt" } ); + + +CreateSymLink(%); + + Expects the keys 'target' and 'file', and uses "system("ln + -sf")" to do it's work. + + Example: + + CreateSymLink( { target => "parent.txt", file => "child.txt" } ); + + +Access(%); + + Expects the key 'file', and simply "cat's" the file to + /dev/null so that the last accessed timestamp is updated. If + the key 'dir' exists, it is prepended to the file path. + + Example: + + Access( { file => "$twrootdir/readme.txt" } ); + Access( { file => "readme.txt", dir => "temp" } ); + + +CreateTestFile(%); + + Expects the key 'file', and optionally the key 'dir'. If 'dir' + is not there, it will simply create the file by echoing the + value of the key 'contents' into into the file. If 'dir' is + there, it will prepend 'dir' to the name of the file. Note + that the directory structure indicated by 'dir' must already + be there. + + Example: + + CreateTestFile( { file => "test.txt", contents => "testing" } ); + CreateTestFile( { file => "test.txt", contents => "testing", dir => "temp" } ); + +UpdateDatabase(%): + + Executes "tripwire -m u " + Optional parameters include: + report -- name of report file to use + secure-mode -- specify a string passed with --secure-mode. + Can be "low" or "high"; default is low + +RunIntegrityCheck(%): + + Executes "tripwire --check " + Optional parameters include: + report -- name of report file to generate + + + +CreateDefaultConfig +SignConfigFile +InitializeDatabase +RunReport +AnalyzeReport +GenerateKeys +GeneratePolicyFile + diff --git a/src/test-harness/twtest.pl b/src/test-harness/twtest.pl new file mode 100755 index 0000000..1f7ea53 --- /dev/null +++ b/src/test-harness/twtest.pl @@ -0,0 +1,157 @@ +#!/usr/bin/perl + +use strict; + +use twtools; + +my @twtests = (); +my @twtestresults = (); + + +###################################################################### +# process command line arguments... +# +sub processCommandLine() { + + while (scalar(@ARGV)) { + + my ($arg) = shift @ARGV; + + + if ($arg =~ /-email/) { + + $twtools::twemail = shift @ARGV; + } + + + if ($arg =~ /-rootdir/) { + + $twtools::twrootdir = shift @ARGV; + } + + + if ($arg =~ /-bin/) { + + $twtools::twbinaries = shift @ARGV; + + } + + + if ($arg !~ /^-/) { + + push @twtests, $arg; + } + + } + + + chomp($twtools::twrootdir); + chomp($twtools::twcwd); + + # Make sure there is no trailing '/' + # + chop($twtools::twcwd) if $twtools::twcwd =~ /\/$/; + chop($twtools::twrootdir) if $twtools::twrootdir =~ /\/$/; + + # report file location, passed to tripwire executables + # if not explicitly specified. + $twtools::reportloc = "$twtools::twrootdir/report/test.twr"; + +} + + +###################################################################### +# try and find any .pm files in the ./tests directory +# which are test scripts... +# +sub prepareListOfTests { + + my @tests; + + opendir(DIR, "./tests"); + @tests = readdir(DIR); + closedir(DIR); + + # These two nasties first pull out only the files + # ending in ".pm", then strip the ".pm" from each + # name, which is necessary later on when we dynamically + # use each module... + # + @twtests = grep(/\.pm$/, @tests); + map { $_ =~ /(.*)\.pm$/; $_ = "$1"; } @twtests; +} + + +###################################################################### +# Call the initialize for each test script passing in +# the current working directory, and the user specified +# root directory for creating the test tree structure. +# +sub runTests { + + my ($module); + my ($ret) = 0; + + for $module (@twtests) { + + # use the module + # + eval qq{use tests::$module}; + + # if that worked, call initialize... + # + if (!$@) { # make sure use succeeded.... + + eval qq{ + + ${module}->initialize() if defined &${module}::initialize + }; + + eval qq { + ${module}->run() if defined &${module}::run + }; + + eval qq { + ${module}->cleanup() if defined &${module}::cleanup + }; + + } + else { + print "no test '$module' found...\n"; + } + } +} + + +###################################################################### +###################################################################### +###################################################################### + +# Turn off buffered output... +$| = 1; + +processCommandLine(); + +prepareListOfTests() if scalar(@twtests) == 0; # only if none were on the cmdline + +print "\n"; +print "initializing for tests...\n\n"; + + +# all tests can assume a base configuration, i.e. default tw.cfg, site and local keys +# +twtools::CreateDefaultConfig(); +twtools::GenerateKeys(); +twtools::SignConfigFile(); + +print "test results:\n"; +print "=============\n\n"; + +# Do the tests... +# +runTests(); + +print "\n\n$twtools::twfailedtests test(s) failed...\n\n"; + +exit($twtools::twfailedtests); + diff --git a/src/test-harness/twtools.pm b/src/test-harness/twtools.pm new file mode 100644 index 0000000..894a161 --- /dev/null +++ b/src/test-harness/twtools.pm @@ -0,0 +1,590 @@ + +package twtools; + +###################################################################### +# +## NOTE: Do not define any of these variables in terms of $twrootdir, +## as the -rootdir evaluation in twtwest happens after these variables +## are initialized... +## +# +BEGIN { + + $twrootdir = "twtest"; + $twcwd = `pwd`; + $twemail = undef; + + $twsitekeyloc = "key/site.key"; + $twlocalkeyloc = "key/local.key"; + $twpolicyloc = "policy/twpol.txt"; + $twcfgloc = "tw.cfg"; + $twsitepass = "testing"; + $twlocalpass = "testing"; + + $twbinaries = "../../../../bin"; + + $twfailedtests = 0; + + # get's setup in twtest... + # + $reportloc = ""; + + %twcfgdirs = ( + + ROOT => '', + POLFILE => 'policy/tw.pol', + DBFILE => 'db/$(HOSTNAME).twd', + REPORTFILE => 'report/$(HOSTNAME)-$(DATE).twr', + SITEKEYFILE => $twsitekeyloc, + LOCALKEYFILE => $twlocalkeyloc + + ); + + %twcfgprops = ( + + EDITOR => '/usr/bin/vi', + LATEPROMPTING => 'false', + LOOSEDIRECTORYCHECKING => 'false', + MAILNOVIOLATIONS => 'true', + EMAILREPORTLEVEL => '3', + REPORTLEVEL => '3', + MAILMETHOD => 'SENDMAIL', + SYSLOGREPORTING => 'false', + MAILPROGRAM => '/usr/lib/sendmail -oi -t' + + ); + +} + +sub logStatus { + + open(LOG, ">>$twrootdir/status.log") || die "couldn't open log file..."; + +# use POSIX qw(strftime); +# my ($now_string) = strftime "%a %b %e %H:%M:%S %Y", localtime; +# print LOG "$now_string\n"; + + print LOG @_; + + close(LOG); +} + +###################################################################### +# Create a default config file in the passed +# in directory, and create the appropriate +# directory structure to along with the config +# file... +# +sub CreateDefaultConfig { + + my ($key, $value); + + # make the root and bin directories if not there + # already... + # + mkdir($twrootdir,0755) if !-e $twrootdir; + mkdir("$twrootdir/bin", 0755); + + open(CFG, ">$twrootdir/twcfg.txt") || die "couldn't open cfg file..."; + + print "generating configuration file...\n" if $verbose; + + # Output the twcfg.txt file... + # + while (($key, $value) = each(%twcfgdirs)) { + + # cfg file must have full paths, so prepend working directory... + # + printf(CFG "%-28s= %s\n", $key, "$twcwd/$twrootdir/$value"); + + # Make the directory structure to go along with it... + # here we pull off everything up to the first /, and use + # it as the name of the directory to create... + # + my ($dir, undef) = split(/\//, $value); + mkdir("$twrootdir/$dir", 0755) if !(-e "$twrootdir/$dir"); + } + + # Output the non directory options to the config file. + # + while (($key, $value) = each(%twcfgprops)) { + + printf(CFG "%-28s= %s\n", $key, $value); + } + + + close(CFG); + + + # Symlink the exe's into our test structure... + # + system("cd $twrootdir/bin && ln -fs $twbinaries/twadmin twadmin"); + system("cd $twrootdir/bin && ln -fs $twbinaries/tripwire tripwire"); + system("cd $twrootdir/bin && ln -fs $twbinaries/siggen siggen"); + system("cd $twrootdir/bin && ln -fs $twbinaries/twprint twprint"); + +} + + +###################################################################### +# Generate the local and site keys if they are not already there... +# +sub GenerateKeys { + + # Don't gen the keys if they are already sitting there... + # + # + if (! (-e "$twrootdir/$twsitekeyloc")) { + print "generating site key...\n" if $verbose; + logStatus(`$twrootdir/bin/twadmin -m G -S $twrootdir/$twsitekeyloc -Q $twsitepass`); + } + + $? && return 0; + + if (! (-e "$twrootdir/$twlocalkeyloc")) { + print "generating local key...\n" if $verbose; + logStatus(`$twrootdir/bin/twadmin -m G -L $twrootdir/$twlocalkeyloc -P $twlocalpass`); + } + + return ($? == 0); +} + + +###################################################################### +# Sign the configuration file... +# +sub SignConfigFile { + + if (!-e "$twrootdir/tw.cfg") { + print "signing configuration file...\n" if $verbose; + logStatus(`$twrootdir/bin/twadmin -m F -Q $twsitepass -c $twrootdir/tw.cfg -S $twrootdir/$twsitekeyloc $twrootdir/twcfg.txt`); + } + + return ($? == 0); +} + + +###################################################################### +# Generate and sign the policy file... Note the contents +# of the policy file are passed in as '$twstr'. +# +sub GeneratePolicyFile { + + my ($twstr) = @_; + + open(FH, ">$twrootdir/$twpolicyloc") || warn $!; + print FH $twstr; + close(FH); + + print "generating policy file...\n" if $verbose; + + logStatus(`$twrootdir/bin/twadmin -m P -c $twrootdir/tw.cfg -Q $twsitepass -p $twrootdir/policy/tw.pol $twrootdir/policy/twpol.txt`); + + return ($? == 0); +} + + +###################################################################### +# Run tripwire to initialize the database... +# +sub InitializeDatabase { + + my ($twmsg) = @_; + + print "initializing database for '$twmsg' test...\n" if $verbose; + logStatus(`$twrootdir/bin/tripwire -m i -P $twsitepass -p $twrootdir/policy/tw.pol -c $twrootdir/tw.cfg`); + + return ($? == 0); +} + + +###################################################################### +# Run tripwire to initialize the database... +# +sub UpdateDatabase { + + my (%params) = %{$_[0]}; + $params{'report'} = $reportloc if( ! defined($params{'report'}) ); + $params{'secure-mode'} = "low" if( ! defined($params{'secure-mode'}) ); + + print "updating database for '$twmsg' test...\n" if $verbose; + logStatus(`$twrootdir/bin/tripwire -m u -a -P $twsitepass -Z $params{'secure-mode'} -p $twrootdir/policy/tw.pol -c $twrootdir/tw.cfg -r $params{'report'}`); + + return ($? == 0); +} + + +###################################################################### +# Use twprint to get a report level 0 report and return +# that. +# +sub RunReport(%) { + + my (%params) = %{$_[0]}; + $params{report} = $reportloc if( ! defined($params{report}) ); + + my (@out) = `$twrootdir/bin/twprint -m r -c $twrootdir/tw.cfg -t 0 -r $params{report}`; + + logStatus(@out); + + return @out; + +} + + +###################################################################### +# Run tripwire to do an integrity check on +# the test data +# +sub RunIntegrityCheck { + + my (%params) = %{$_[0]}; + $params{report} = $reportloc if( ! defined($params{report}) ); + + print("running integrity check for test '$twmsg'...\n") if $verbose; + logStatus(`$twrootdir/bin/tripwire -m c -r $params{report} -p $twrootdir/policy/tw.pol -c $twrootdir/tw.cfg 2>&1`); + + return ($? & 8); +} + + +###################################################################### +# This function knows how to parse a level 0 report as +# produced by twprint. It pulls out the count of each type +# of violation and returns them as a list... +# +sub AnalyzeReport { + + # Sheers off the first line to get to + # the actual status line... + # + my (undef, $twstatus) = @_; + +# print "*** $twstatus\n"; + + # split the report summary line into it's fields + # + my (undef, undef, undef, $violations, $severity, $added, $removed, $changed) = + split(/ /, $twstatus); + + + # Split out the count for each type of + # violation. + # + (undef, $violations) = split(/:/, $violations); + (undef, $added) = split(/:/, $added); + (undef, $removed) = split(/:/, $removed); + (undef, $changed) = split(/:/, $changed); + + # return the counts. + # + return ($violations, $added, $removed, $changed); +} + + +###################################################################### +# Make the file bigger... +# +sub MakeBigger(%) { + + my (%params) = %{$_[0]}; + + my ($twfile); + + if (defined $params{dir}) { + $twfile = "$twrootdir/$params{dir}/$params{file}"; + } + else { + $twfile = "$twrootdir/$params{file}"; + } + + system("echo more >> $twfile"); +} + + + +###################################################################### +# Make the file smaller, i.e. 0 byes ;) +# +sub MakeSmaller(%) { + + my (%params) = %{$_[0]}; + + my ($twfile); + + if (defined $params{dir}) { + $twfile = "$twrootdir/$params{dir}/$params{file}"; + } + else { + $twfile = "$twrootdir/$params{file}"; + } + + system("echo -n > $twfile"); +} + + + +###################################################################### +# Access (read) the file. +# +sub Access(%) { + + my (%params) = %{$_[0]}; + + my ($twfile); + + if (defined $params{dir}) { + $twfile = "$twrootdir/$params{dir}/$params{file}"; + } + else { + $twfile = "$twrootdir/$params{file}"; + } + + # Here, we simply access (read) the file, thus + # changing the last accessed timestamp. + # + system("cat $twfile > /dev/null"); + +} + + +###################################################################### +# +# Chmod the file -- irrelevant what we chmod it +# to, we just want to affect a change. +# +sub Chmod(%) { + + my (%params) = %{$_[0]}; + + my ($twfile); + + if (defined $params{dir}) { + $twfile = "$twrootdir/$params{dir}/$params{file}"; + } + else { + $twfile = "$twrootdir/$params{file}"; + } + + # Fake a change to the file which should be caught... + # + system("chmod a+w $twfile"); + + $? && die "chmod failed for $twfile\n"; +} + + +###################################################################### +# +# Create a symlink between target and file... +# +sub CreateSymLink(%) { + + my (%params) = %{$_[0]}; + + # Just create a symlink... + # + system("cd $twrootdir && ln -fs $params{target} $params{file}"); + + $? && die "ln -s failed for $params{target} -> $params{file}\n"; +} + + + +###################################################################### +# +# Create a hard link between target and file... +# +sub CreateHardLink(%) { + + my (%params) = %{$_[0]}; + + # Just create a hard link... + # + system("cd $twrootdir && ln -f $params{target} $params{file}"); + + $? && die "ln failed for $params{target} -> $params{file}\n"; +} + + +###################################################################### +# CreateFile -- create a file with the specified contents +# +# input: path -- path to the file; relative to $root +# contents -- string to put in the file +# +sub CreateFile(%) +{ + my (%params) = %{$_[0]}; + + my ($path) = $params{'file'}; + my ($contents) = $params{'contents'}; + + my ($twfile); + + if (defined $params{dir}) { + $twfile = "$twrootdir/$params{dir}/$path"; + } + else { + $twfile = "$twrootdir/$path"; + } + + system( "echo $contents > $twfile" ); + + $? && die "Create file failed for $twfile\n"; +} + +###################################################################### +# RemoveFile -- removes the named file +# +sub RemoveFile(%) +{ + my (%params) = %{$_[0]}; + my ($path) = $params{'file'}; + + if( -e "$twrootdir/$path" ) + { + system( "rm -f $twrootdir/$path" ); + } + + $? && die "Remove file failed for $twrootdir/$path\n"; +} + + +###################################################################### +# CreateDir -- create a directory +# +sub CreateDir(%) +{ + my (%params) = %{$_[0]}; + + my ($dir) = $params{'dir'}; + + # NOTE: mkdir fails if it is already a directory! + # + if( ! -d "$twrootdir/$dir" ) + { + system( "rm -f $twrootdir/$dir" ); + system( "mkdir -p $twrootdir/$dir" ); + + $? && die "Mkdir failed for $twrootdir/$dir\n"; + } +} + +###################################################################### +# MoveFile -- move a file from one place to another +# NOTE: file names are relative to $root +# +# input: old_name -- name of file to move +# new_name -- where it should be moved to +# +sub MoveFile +{ + my (%params) = %{$_[0]}; + my ($file) = $params{'file'}; + my ($target) = $params{'target'}; + + system( "mv $twrootdir/$file $twrootdir/$target" ); + + $? && die "mv $twrootdir/$file $twrootdir/$target failed!\n"; +} + +###################################################################### +# This function iterates through the sub tests +# performing the requested operations and verifying +# that the expected and actual violation counts are +# the same. +# +sub RunIntegrityTests(\%) { + + my %tests = %{$_[0]}; + my ($violations, $added, $removed, $changed) = (0,0,0,0); + + + ######################################################### + # + # Here we tally up the count of each violation which + # should occur + # + map { + + my ($v,undef,$a,$r,$c) = split(/ /, $tests{$_}{violations}); + + (undef, $v) = split(/:/, $v); + (undef, $a) = split(/:/, $a); + (undef, $r) = split(/:/, $r); + (undef, $c) = split(/:/, $c); + + $violations += $v; + $added += $a; + $removed += $r; + $changed += $c; + + if ($violations != ($added + $removed + $changed)) { + + die "V: does not == A: + R: + C: for $_\n\n"; + } + + } sort keys %tests; + + + ######################################################### + # + # Call the file create function for each sub-test... + # + map { + + if (defined $tests{$_}{createFunc}) { + + $tests{$_}{createFunc}->($tests{$_}); + } + + } sort keys %tests; + + ######################################################### + # + # Now that the files are there, create the initial database... + # + InitializeDatabase(""); + + + ######################################################### + # + # Call the file change function for each sub-test... + # + map { + + if (defined $tests{$_}{changeFunc}) { + + $tests{$_}{changeFunc}->($tests{$_}); + } + + } sort keys %tests; + + + ######################################################### + # + # Run the integrity check... + # + RunIntegrityCheck(); + + + ######################################################### + # + # Analyze the report generated by the integrity check... + # + my @twresults = RunReport( { dir => "this"} ); + my ($actualViolations, $actualAdded, $actualRemoved, $actualChanged) = AnalyzeReport(@twresults); + + # Actual and expected violations should match if everything went as + # planned. + # + return ($actualViolations == $violations && $actualAdded == $added && + $actualRemoved == $removed && $actualChanged == $changed); +} + + +END { +} + +1; diff --git a/src/test/stdtest.cpp b/src/test/stdtest.cpp new file mode 100644 index 0000000..483df60 --- /dev/null +++ b/src/test/stdtest.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtest.cpp +// Date....: 5/12/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtest.h" + +// eof: stdtest.cpp diff --git a/src/test/stdtest.h b/src/test/stdtest.h new file mode 100644 index 0000000..291a3fc --- /dev/null +++ b/src/test/stdtest.h @@ -0,0 +1,33 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "core/stdcore.h" + diff --git a/src/test/test.cpp b/src/test/test.cpp new file mode 100644 index 0000000..c44e2bc --- /dev/null +++ b/src/test/test.cpp @@ -0,0 +1,336 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// test.cpp +// +// main() for all the component test driver functions + +#include "stdtest.h" + +#include "core/core.h" +#include "db/db.h" +#include "twcrypto/twcrypto.h" + +#ifdef PARSER_PRESENT +#include "parser/parser.h" +#endif + +#include "tw/tw.h" +#include "fco/fco.h" + + +#include "fs/fs.h" +#include "util/util.h" + +#include +#include "core/debug.h" +#include "core/error.h" +#include "core/twlocale.h" +#include "test.h" +#include "core/errorbucketimpl.h" +#include "tw/twinit.h" +#include "tw/twutil.h" +#include "fco/fcogenre.h" +#include "fco/genreswitcher.h" +#include "core/growheap.h" +#include "db/blockfile.h" +#include "db/blockrecordarray.h" +#include "db/hierdatabase.h" + + +// the test routines +void TestFCOName(); +void TestFCOTest(); +void TestFCOSetImpl(); +void TestFCOSpec(); +void TestFCOPropVector(); +void TestFileHeader(); +void TestFSPropSet(); +void TestFSDataSource(); +void TestFCOSpecImpl(); +void TestFSPropCalc(); +void TestFCOPropImpl(); +void TestFCOCompare(); +//void TestTripwire(); +void TestFCOSetUtil(); +void TestWin32FSServices(); +void TestFCOSpecList(); +void TestFCOReport(); +void TestArchive(); +void TestSerializer(); +void TestSerializerImpl(); +void TestRefCountObj(); +void TestSignature(); +void TestSerRefCountObj(); +#if IS_UNIX +void TestUnixFSServices(); +#endif +//void TestFCODatabase(); +void TestError(); +void TestDebug(); +void TestFcoSpecUtil(); +void TestTypes(); +void TestTCHAR(); +void TestErrorBucketImpl(); +void TestHashTable(); +//void TestTextReportViewer(); +void TestFCONameTbl(); +void TestConfigFile(); + +#ifdef PARSER_PRESENT +void TestPolicyParser(); +#endif//PARSER_PRESENT + +void TestFCOSpecHelper(); +void TestCrypto(); +void TestCryptoArchive(); +void TestFCOSpecAttr(); +void TestCmdLineParser(); +void TestTaskTimer(); +void TestObjectPool(); +void TestKeyFile(); +void TestFCOSetCached(); +void TestTWUtil(); +void TestFSPropDisplayer(); +void TestFSPropDisplayer(); +void TestGenre(); +void TestFSDataSourceIter(); +void TestGenerateDb(); +void TestHierDatabaseInteractive(); +void TestGenreSwitcher(); +void TestDbDataSource(); +void TestGenreSpecList(); +void TestIntegrityCheck(); +void TestFCODatabaseFile(); +void TestWchar16(); +void TestStringEncoder(); +#ifdef TSS_TEST +void TestDisplayEncoder(); +#endif +void TestGrowHeap(); +void TestPlatform(); +void TestBlockFile(); +void TestBlockRecordArray(); +void TestHierDatabaseInteractive(); +void TestTWLocale(); +void TestFileUtil(); +void TestFCONameTranslator(); +void TestCodeConverter(); +/// This is easier than all the (cpp) files and declarations +#include "core/stringutil_t.h" + +void Usage() +{ + TCERR << _T("Usage: test {all | testid [testid ...]}\n") + _T("\n") + _T("Ex: test 1 2 3 12\n") + _T("(runs test id's 1, 2, 3, and 12)\n\n"); +} + +const int MAX_TEST_ID = 100; + +static void Test(int testID) +{ + switch (testID) + { + case 1: TestArchive(); break; + case 2: TestCmdLineParser(); break; + case 3: TestCrypto(); break; + case 4: TestCryptoArchive(); break; + case 5: TestDebug(); break; + case 6: TestError(); break; + case 7: TestErrorBucketImpl(); break; + //case 8: TestFCOCompare(); break; + //case 9: TestFCODatabase(); break; + //case 11: TestFCOErrorQueue(); break; + case 12: TestFCOName(); break; + case 13: TestFCONameTbl(); break; + case 14: TestFCOPropVector(); break; + case 15: TestFCOPropImpl(); break; + case 16: TestFCOReport(); break; + //case 17: TestFCOSetCached(); break; + case 18: TestFCOSetImpl(); break; + //case 19: TestFCOSetUtil(); break; + case 20: TestFCOSpecAttr(); break; + case 21: TestFCOSpecHelper(); break; + case 22: TestFCOSpecList(); break; + case 23: TestFcoSpecUtil(); break; + case 24: TestFileHeader(); break; + //case 25: TestFSDataSource(); break; + case 26: TestFSPropSet(); break; + //case 27: TestFSPropCalc(); break; + case 28: TestFCOSpecImpl(); break; + case 29: TestHashTable(); break; + case 30: TestObjectPool(); break; + case 31: TestRefCountObj(); break; + case 32: TestSerializerImpl(); break; + case 33: TestSerRefCountObj(); break; + case 34: TestSignature(); break; + case 35: TestTaskTimer(); break; + //case 36: TestTripwire(); break; + //case 37: TestTextReportViewer(); break; + case 39: TestSerRefCountObj(); break; + case 40: TestError(); break; + //case 41: TestFCODatabase(); break; + case 42: TestHashTable(); break; + case 43: TestTCHAR(); break; + #if IS_UNIX + case 44: TestUnixFSServices(); break; + #endif + case 46: TestConfigFile(); break; +#ifdef PARSER_PRESENT + case 47: TestPolicyParser(); break; +#endif//PARSER_PRESENT + case 48: TestKeyFile(); break; + case 49: TestTWUtil(); break; + case 50: TestFSPropDisplayer(); break; + case 52: TestGenre(); break; + case 53: TestFSDataSourceIter(); break; + //case 54: TestGenerateDb(); break; + case 55: TestHierDatabaseInteractive(); break; + case 56: TestGenreSwitcher(); break; + case 57: TestDbDataSource(); break; + case 58: TestGenreSpecList(); break; + //case 59: TestIntegrityCheck(); break; + case 65: TestWchar16(); break; + case 66: TestStringEncoder(); break; +#ifdef TSS_TEST + case 67: TestDisplayEncoder(); break; +#endif + case 69: TestGrowHeap(); break; + case 70: TestPlatform(); break; + case 71: TestBlockFile(); break; + case 72: TestBlockRecordArray(); break; + case 73: TestHierDatabaseInteractive(); break; + case 74: TestFileUtil(); break; + case 75: TestTWLocale(); break; + case 76: TestFCONameTranslator(); break; + case 77: TestStringUtil(); break; + case 78: TestCodeConverter(); break; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// cTest +/////////////////////////////////////////////////////////////////////////////// +TSS_ImplementPackage( cTest ) + +cTest::cTest() +{ + TSS_Dependency( cCore ); + TSS_Dependency( cDb ); + TSS_Dependency( cTWCrypto ); +#ifdef PARSER_PRESENT + TSS_Dependency( cParser ); +#endif//PARSER_PRESENT + TSS_Dependency( cTW ); + TSS_Dependency( cFCO ); + TSS_Dependency( cFS ); + TSS_Dependency( cUtil ); + +// no erros excluivly for test package +// TSS_REGISTER_PKG_ERRORS( test ) +} + +/////////////////////////////////////////////////////////////////////////////// +// terminate and unexpected handlers +// TODO: move these to a common library +/////////////////////////////////////////////////////////////////////////////// +void tw_terminate_handler() +{ + fputs("### Internal Error.\n### Terminate Handler called.\n### Exiting...\n", stderr); + exit(1); +} + +void tw_unexpected_handler() +{ + fputs("### Internal Error.\n### Unexpected Exception Handler called.\n### Exiting...\n", stderr); + exit(1); +} + +int _tmain(int argc, TCHAR** argv) +{ + std::cout << "Test: Init" << std::endl; + + try + { + std::cout << "Test: Setup" << std::endl; + std::cout << "Test: argc - " << argc << std::endl; + std::cout << "Test: *argv - " << argv[0] << std::endl; + + EXCEPTION_NAMESPACE set_terminate(tw_terminate_handler); + EXCEPTION_NAMESPACE set_unexpected(tw_unexpected_handler); + + cTWInit twInit; + twInit.Init( argv[0] ); + + // set up the debug output + cDebug::AddOutTarget(cDebug::OUT_STDOUT); + //cDebug::SetDebugLevel(cDebug::D_NEVER); + cDebug::SetDebugLevel(cDebug::D_DETAIL); + //cDebug::SetDebugLevel(cDebug::D_DEBUG); + + int i; + + if (argc < 2) + Usage(); + else if (_tcsicmp(argv[1], _T("all")) == 0) + // run all the tests + for (i = 1; i <= MAX_TEST_ID; ++i) + Test(i); + else + for (i = 1; i < argc; ++i) + Test(_ttoi(argv[i])); // Note: if atoi returns 0, Test() will handle it fine. + + } + catch (eError& error) + { + cTWUtil::PrintErrorMsg(error); + ASSERT(false); + } + catch (...) + { + TCERR << _T("Unhandled exception caught!"); + ASSERT(false); + } + + // make sure all the refrence counted objects have been destroyed + // this test always fails because of the static cFCONameTbl + //TEST(cRefCountObj::AllRefCountObjDestoryed() == true); + + // force user to hit + + return 1; +} + + + diff --git a/src/test/test.h b/src/test/test.h new file mode 100644 index 0000000..83c36bd --- /dev/null +++ b/src/test/test.h @@ -0,0 +1,90 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// test.h -- This header file is used included by all component test modules. +// It provides an ASSERT() like macro that causes a breakpoint to occur +// even in release mode. +// It also provides some values that are platform dependant such as a +// well defined temporary directory +// + +#ifndef __TEST_H +#define __TEST_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +#if IS_UNIX +#include +using namespace std; +#endif + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include "core/package.h" + + +TSS_BeginPackage( cTest ) + +public: + cTest(); + +TSS_EndPackage( cTest ) + +/////////////////////////////////////////////////////////////////////////////// +// TEST() -- Works like ASSERT() but it also breaks during release mode + +#if IS_UNIX + +#define TEST(exp) if (!(exp)) \ + { \ + std::cerr<<"TEST(" << #exp << ") failure, file " << __FILE__ << " line " << __LINE__ << std::endl; \ + exit(-1); \ + } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Platform dependancies + +#if IS_UNIX +#define TEMP_DIR _T("/tmp") +#define TEMP_DIR_N "/tmp" +#endif + +#endif // __TEST_H + diff --git a/src/test/test.mak b/src/test/test.mak new file mode 100644 index 0000000..a344676 --- /dev/null +++ b/src/test/test.mak @@ -0,0 +1,227 @@ +# +# test.mak +# See common_rules.mak for comments + +include ../make_include/$(SYSPRE).inc + +EXECUTABLE = test +TYPE = BINARY + +ADD_OBJS = file_unix.o unixfsservices.o unixfsservices_t.o archive_t.o cmdlineparser_t.o codeconvert_t.o debug_t.o displayencoder_t.o error_t.o errorbucketimpl_t.o file_t.o fileheader_t.o growheap_t.o hashtable_t.o objectpool_t.o platform_t.o refcountobj_t.o resources_t.o serializer_t.o serializerimpl_t.o srefcountobj_t.o tasktimer_t.o tchar_t.o twlocale_t.o types_t.o usernotifystdout_t.o wchar16_t.o blockfile_t.o blockrecordarray_t.o hierdatabase_t.o fcocompare_t.o fconame_t.o fconametbl_t.o fconametranslator_t.o fcopropimpl_t.o fcopropvector_t.o fcosetimpl_t.o fcospec_t.o fcospecattr_t.o fcospechelper_t.o fcospeclist_t.o fcospecutil_t.o fsspec_t.o genre_t.o genrespeclist_t.o genreswitcher_t.o signature_t.o fileutil_t.o stringencoder_t.o fsdatasourceiter_t.o fsobject_t.o fspropcalc_t.o fspropdisplayer_t.o fspropset_t.o configfile_t.o dbdatasource_t.o fcodatabasefile_t.o fcoreport_t.o textreportviewer_t.o twutil_t.o cryptoarchive_t.o crytpo_t.o keyfile_t.o + +ADD_SRCS = ../core/unix/file_unix.cpp ../core/unix/unixfsservices.cpp ../core/unix/unixfsservices_t.cpp ../core/archive_t.cpp ../core/cmdlineparser_t.cpp ../core/codeconvert_t.cpp ../core/debug_t.cpp ../core/displayencoder_t.cpp ../core/error_t.cpp ../core/errorbucketimpl_t.cpp ../core/file_t.cpp ../core/fileheader_t.cpp ../core/growheap_t.cpp ../core/hashtable_t.cpp ../core/objectpool_t.cpp ../core/platform_t.cpp ../core/refcountobj_t.cpp ../core/resources_t.cpp ../core/serializer_t.cpp ../core/serializerimpl_t.cpp ../core/srefcountobj_t.cpp ../core/tasktimer_t.cpp ../core/tchar_t.cpp ../core/twlocale_t.cpp ../core/types_t.cpp ../core/usernotifystdout_t.cpp ../core/wchar16_t.cpp ../db/blockfile_t.cpp ../db/blockrecordarray_t.cpp ../db/hierdatabase_t.cpp ../fco/fcocompare_t.cpp ../fco/fconame_t.cpp ../fco/fconametbl_t.cpp ../fco/fconametranslator_t.cpp ../fco/fcopropimpl_t.cpp ../fco/fcopropvector_t.cpp ../fco/fcosetimpl_t.cpp ../fco/fcospec_t.cpp ../fco/fcospecattr_t.cpp ../fco/fcospechelper_t.cpp ../fco/fcospeclist_t.cpp ../fco/fcospecutil_t.cpp ../fco/fsspec_t.cpp ../fco/genre_t.cpp ../fco/genrespeclist_t.cpp ../fco/genreswitcher_t.cpp ../fco/signature_t.cpp ../util/fileutil_t.cpp ../util/stringencoder_t.cpp ../fs/fsdatasourceiter_t.cpp ../fs/fsobject_t.cpp ../fs/fspropcalc_t.cpp ../fs/fspropdisplayer_t.cpp ../fs/fspropset_t.cpp ../tw/configfile_t.cpp ../tw/dbdatasource_t.cpp ../tw/fcodatabasefile_t.cpp ../tw/fcoreport_t.cpp ../tw/textreportviewer_t.cpp ../tw/twutil_t.cpp ../twcrypto/cryptoarchive_t.cpp ../twcrypto/crytpo_t.cpp ../twcrypto/keyfile_t.cpp + + +DSP_OBJS = test.o +DSP_SRCS = test.cpp + +OBJS = $(DSP_OBJS) $(ADD_OBJS) +SRCS = $(DSP_SRCS) $(ADD_SRCS) + + +include ../make_include/common_rules.mak + + +##### targets for object files ##### + +# Here is the list of how to compile ADD_OBJS from ADD_SRCS +# Because of the directory differences in the .cpp files, these have to be itemized +# individually and cannot be included in the generic target in common_rules.mak + +$(OBJDIR)/file_unix.o : ../core/unix/file_unix.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/unixfsservices.o : ../core/unix/unixfsservices.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/unixfsservices_t.o : ../core/unix/unixfsservices_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/archive_t.o : ../core/archive_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/cmdlineparser_t.o : ../core/cmdlineparser_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/codeconvert_t.o : ../core/codeconvert_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/debug_t.o : ../core/debug_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/displayencoder_t.o : ../core/displayencoder_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/error_t.o : ../core/error_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/errorbucketimpl_t.o : ../core/errorbucketimpl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/file_t.o : ../core/file_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fileheader_t.o : ../core/fileheader_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/growheap_t.o : ../core/growheap_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/hashtable_t.o : ../core/hashtable_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/objectpool_t.o : ../core/objectpool_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/platform_t.o : ../core/platform_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/refcountobj_t.o : ../core/refcountobj_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/resources_t.o : ../core/resources_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/serializer_t.o : ../core/serializer_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/serializerimpl_t.o : ../core/serializerimpl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/srefcountobj_t.o : ../core/srefcountobj_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/tasktimer_t.o : ../core/tasktimer_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/tchar_t.o : ../core/tchar_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/twlocale_t.o : ../core/twlocale_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/types_t.o : ../core/types_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/usernotifystdout_t.o : ../core/usernotifystdout_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/wchar16_t.o : ../core/wchar16_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/blockfile_t.o : ../db/blockfile_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/blockrecordarray_t.o : ../db/blockrecordarray_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/hierdatabase_t.o : ../db/hierdatabase_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/acl_t.o : ../fco/acl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcocompare_t.o : ../fco/fcocompare_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +test_$(SYSPRE)_r/fconame_t.o : ../fco/fconame_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fconame_t.o : ../fco/fconame_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fconametbl_t.o : ../fco/fconametbl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fconametranslator_t.o : ../fco/fconametranslator_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcopropimpl_t.o : ../fco/fcopropimpl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcopropvector_t.o : ../fco/fcopropvector_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcosetimpl_t.o : ../fco/fcosetimpl_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcospec_t.o : ../fco/fcospec_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcospecattr_t.o : ../fco/fcospecattr_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcospechelper_t.o : ../fco/fcospechelper_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcospeclist_t.o : ../fco/fcospeclist_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcospecutil_t.o : ../fco/fcospecutil_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fsspec_t.o : ../fco/fsspec_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/genre_t.o : ../fco/genre_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/genrespeclist_t.o : ../fco/genrespeclist_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/genreswitcher_t.o : ../fco/genreswitcher_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/sid_t.o : ../fco/sid_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/signature_t.o : ../fco/signature_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fileutil_t.o : ../util/fileutil_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/stringencoder_t.o : ../util/stringencoder_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fsdatasourceiter_t.o : ../fs/fsdatasourceiter_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fsobject_t.o : ../fs/fsobject_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fspropcalc_t.o : ../fs/fspropcalc_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fspropdisplayer_t.o : ../fs/fspropdisplayer_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fspropset_t.o : ../fs/fspropset_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/configfile_t.o : ../tw/configfile_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/dbdatasource_t.o : ../tw/dbdatasource_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcodatabasefile_t.o : ../tw/fcodatabasefile_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/fcoreport_t.o : ../tw/fcoreport_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/textreportviewer_t.o : ../tw/textreportviewer_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/twutil_t.o : ../tw/twutil_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/cryptoarchive_t.o : ../twcrypto/cryptoarchive_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/crytpo_t.o : ../twcrypto/crytpo_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< + +$(OBJDIR)/keyfile_t.o : ../twcrypto/keyfile_t.cpp + $(CXX) -o $@ $(CXXFLAGS) $(DEFINES) -c $< diff --git a/src/tripwire/Makefile.am b/src/tripwire/Makefile.am new file mode 100644 index 0000000..f51126c --- /dev/null +++ b/src/tripwire/Makefile.am @@ -0,0 +1,19 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 + +INCLUDES = -I.. +LIBS = -ltripwire -lcryptlib @LIBS@ +LDFLAGS = @LDFLAGS@ -L../../lib + +sbin_PROGRAMS = tripwire +tripwire_SOURCES = \ + generatedb.cpp integritycheck.cpp mailmessage.cpp pipedmailmessage.cpp \ + policyupdate.cpp smtpmailmessage.cpp stdtripwire.cpp syslog_trip.cpp \ + tripwire.cpp tripwireerrors.cpp tripwiremain.cpp tripwirestrings.cpp \ + tripwireutil.cpp twcmdline.cpp twcmdlineutil.cpp updatedb.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +CLEANFILES = ../../bin/tripwire ../../lib/libtripwire.a + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin diff --git a/src/tripwire/Makefile.in b/src/tripwire/Makefile.in new file mode 100644 index 0000000..861066a --- /dev/null +++ b/src/tripwire/Makefile.in @@ -0,0 +1,429 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(tripwire_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +sbin_PROGRAMS = tripwire$(EXEEXT) +subdir = src/tripwire +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(sbin_PROGRAMS) +am_tripwire_OBJECTS = generatedb.$(OBJEXT) integritycheck.$(OBJEXT) \ + mailmessage.$(OBJEXT) pipedmailmessage.$(OBJEXT) \ + policyupdate.$(OBJEXT) smtpmailmessage.$(OBJEXT) \ + stdtripwire.$(OBJEXT) syslog_trip.$(OBJEXT) tripwire.$(OBJEXT) \ + tripwireerrors.$(OBJEXT) tripwiremain.$(OBJEXT) \ + tripwirestrings.$(OBJEXT) tripwireutil.$(OBJEXT) \ + twcmdline.$(OBJEXT) twcmdlineutil.$(OBJEXT) updatedb.$(OBJEXT) +tripwire_OBJECTS = $(am_tripwire_OBJECTS) +tripwire_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(tripwire_SOURCES) +DIST_SOURCES = $(tripwire_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ -L../../lib +LIBOBJS = @LIBOBJS@ +LIBS = -ltripwire -lcryptlib @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 +INCLUDES = -I.. +tripwire_SOURCES = \ + generatedb.cpp integritycheck.cpp mailmessage.cpp pipedmailmessage.cpp \ + policyupdate.cpp smtpmailmessage.cpp stdtripwire.cpp syslog_trip.cpp \ + tripwire.cpp tripwireerrors.cpp tripwiremain.cpp tripwirestrings.cpp \ + tripwireutil.cpp twcmdline.cpp twcmdlineutil.cpp updatedb.cpp + +CLEANFILES = ../../bin/tripwire ../../lib/libtripwire.a +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tripwire/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/tripwire/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$f"; \ + done + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +tripwire$(EXEEXT): $(tripwire_OBJECTS) $(tripwire_DEPENDENCIES) + @rm -f tripwire$(EXEEXT) + $(CXXLINK) $(tripwire_LDFLAGS) $(tripwire_OBJECTS) $(tripwire_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-sbinPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am uninstall-sbinPROGRAMS + + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/tripwire/generatedb.cpp b/src/tripwire/generatedb.cpp new file mode 100644 index 0000000..09c20ef --- /dev/null +++ b/src/tripwire/generatedb.cpp @@ -0,0 +1,206 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// generatedb.cpp + +#include "stdtripwire.h" +#include "tripwirestrings.h" +#include "generatedb.h" +#include "core/debug.h" +#include "core/error.h" +#include "fco/twfactory.h" +#include "fco/fcospeclist.h" +#include "tw/dbdatasource.h" +#include "fco/genreswitcher.h" +#include "fco/fcopropcalc.h" +#include "fco/fcopropset.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropdisplayer.h" +#include "tripwireutil.h" +#include "fco/fcodatasourceiter.h" + +// for verbose output +#include "core/usernotify.h" +#include "fco/fconametranslator.h" + +/////////////////////////////////////////////////////////////////////////////// +// util_ProcessDir +// +// this returns true if at least one object was added to the directory. +/////////////////////////////////////////////////////////////////////////////// +static void util_ProcessDir( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, iFCOSpec* pSpec, iFCOPropCalc* pPC, iFCOPropDisplayer* pPD ) +{ + ASSERT( ! dbIter.Done() ); + ASSERT( ! pIter->Done() ); + ASSERT( pIter->CanDescend() ); + ASSERT( dbIter.CanDescend() ); + if( ! pIter->CanDescend() ) + return; + // + // first, descend into the directory + // + pIter->Descend(); + dbIter.Descend(); + // + // now, iterate through the data source, adding entries to the database ... + // + for( pIter->SeekBegin(); ! pIter->Done(); pIter->Next() ) + { + // + // don't continue if the spec says we shouldn't + // + if( pSpec->ShouldStopDescent( pIter->GetName() ) ) + { + continue; + } + // TODO -- do I need to check the db iter to see if the given item already exists? + // this should never really happen unless the data source iter is screwed up. + // TODO -- use a smart reference counted object pointer here to release the object when it + // goes out of scope. + iFCO* pFCO = pIter->CreateFCO(); + if( pFCO ) + { + cTripwireUtil::CalcProps( pFCO, pSpec, pPC, pPD ); + dbIter.AddFCO( pIter->GetShortName(), pFCO ); + pFCO->Release(); + // + // descend into this directory if we can... + // + if( pIter->CanDescend() ) + { + if( ! dbIter.CanDescend() ) + { + dbIter.AddChildArray(); + } + std::auto_ptr pCopy( pIter->CreateCopy() ); + util_ProcessDir( dbIter, pCopy.get(), pSpec, pPC, pPD ); + // + // if no files were added, remove the child array... + // + if( dbIter.CanRemoveChildArray() ) + { + dbIter.RemoveChildArray(); + } + } + } + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +void cGenerateDb::Execute( const cFCOSpecList& specList, cHierDatabase& db, iFCOPropDisplayer* pPD, cErrorBucket* pBucket, uint32 flags ) +{ + // TODO -- assert the db is empty or clear it out myself! + + std::auto_ptr pDSIter(iTWFactory::GetInstance()->CreateDataSourceIter()); + + // + // set up the database's iterator... + // I assume the current genre is correct... + // + cDbDataSourceIter dbIter( &db ); + + // + // set the iterators' error bucket... + // + pDSIter->SetErrorBucket(pBucket); + dbIter.SetErrorBucket(pBucket); + + // + // this is the object that will calculate all of the properties of the fcos. + // + std::auto_ptr pPC(iTWFactory::GetInstance()->CreatePropCalc()); + pPC->SetErrorBucket( pBucket ); + if( flags & FLAG_ERASE_FOOTPRINTS_GD ) + { + pPC->SetCalcFlags( iFCOPropCalc::DO_NOT_MODIFY_PROPERTIES ); + dbIter.SetIterFlags( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + pDSIter->SetIterFlags( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + } + + // + // iterate over all of the specs... + // + cFCOSpecListCanonicalIter specIter(specList); + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + // verbose output + TW_NOTIFY_VERBOSE( _T("%s %s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_PROCESSING ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( specIter.Spec()->GetStartPoint() ).c_str() ); + // + // have the iterators seek to the appropriate starting point + // + pDSIter->SeekToFCO ( specIter.Spec()->GetStartPoint(), false ); // false means don't generate my peers... + if( ! pDSIter->Done() ) + { + iFCO* pFCO = pDSIter->CreateFCO(); + if( pFCO ) + { + dbIter.CreatePath( specIter.Spec()->GetStartPoint() ); + // + // ok, now process this directory + // we need to add the start point here, since the first thing the ProcessDir function does is + // Descend(). + // + cTripwireUtil::CalcProps( pFCO, specIter.Spec(), pPC.get(), pPD ); + dbIter.SetFCOData( pFCO ); + pFCO->Release(); + // + // if this is a directory, process its children... + // + if( pDSIter->CanDescend() && (! specIter.Spec()->ShouldStopDescent( pDSIter->GetName() )) ) + { + // make the child array, if it doesn't exist... + // + if( ! dbIter.CanDescend() ) + { + dbIter.AddChildArray(); + } + std::auto_ptr pCopy( pDSIter->CreateCopy() ); + util_ProcessDir( dbIter, pCopy.get(), specIter.Spec(), pPC.get(), pPD ); + // + // if no files were added, remove the child array... + // + if( dbIter.CanRemoveChildArray() ) + { + dbIter.RemoveChildArray(); + } + } + } + } + + } +} + diff --git a/src/tripwire/generatedb.h b/src/tripwire/generatedb.h new file mode 100644 index 0000000..c4d4535 --- /dev/null +++ b/src/tripwire/generatedb.h @@ -0,0 +1,65 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// generatedb.h +// +// cGenerateDb -- a class that generates a tripwire database... +// +#ifndef __GENERATEDB_H +#define __GENERATEDB_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +class cErrorBucket; +class cFCOSpecList; +class cHierDatabase; +class iFCOPropDisplayer; + +class cGenerateDb +{ +public: + static void Execute( const cFCOSpecList& specList, cHierDatabase& db, iFCOPropDisplayer* pPD, cErrorBucket* pBucket, uint32 flags = 0 ); + // generates a tripwire database; this asserts that the database is open + + enum Flags + { + FLAG_ERASE_FOOTPRINTS_GD = 0x00000001 + // when this flag is set, cGenerateDb will attempt to leave no footprints when + // creating the database for instance, cGenerateDb will tell the property calculator + // to reset access times. + }; +}; + +#endif //__GENERATEDB_H + diff --git a/src/tripwire/generatedb_t.cpp b/src/tripwire/generatedb_t.cpp new file mode 100644 index 0000000..d9f2906 --- /dev/null +++ b/src/tripwire/generatedb_t.cpp @@ -0,0 +1,95 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// generatedb_t + +#include "stdtripwire.h" +#include "generatedb.h" +#include "core/fsservices.h" +#include "core/debug.h" +#include "core/errorbucketimpl.h" +#include "fco/fcospecimpl.h" +#include "fco/fcospeclist.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "fco/genreswitcher.h" +#include "db/hierdatabase.h" +#include "parser/policyparser.h" +#include "test/test.h" + +#include + +void TestGenerateDb() +{ + cDebug d("TestGenerateDb"); + + try + { + iFCONameInfo* pInfo = iTWFactory::GetInstance()->GetNameInfo(); + cErrorTracer et; + cHierDatabase db( pInfo->IsCaseSensitive(), pInfo->GetDelimitingChar() ); + db.Open( _T("c:/tmp/tw.db"), 5, true ); + cHierDatabase::iterator iter( &db ); + // + // make some specs... + // + cGenreSpecListVector slv; + std::ifstream in; + in.open("c:/tmp/pol.pol"); + if(in.fail()) + { + d.TraceError( "Unable to open policy file!\n" ); + TEST( false ); + return; + } + cPolicyParser parser(in); + parser.Execute(slv, &et); + + + // + // ok, time to integrity check! + // + cGenreSpecListVector::iterator at; + for( at = slv.begin(); at != slv.end(); at++ ) + { + cGenerateDb::Execute( + at->GetSpecList(), + db, + cGenreSwitcher::GetInstance()->GetFactoryForGenre( at->GetGenre() )->CreatePropDisplayer(), + &et + ); + } + } + catch( eError& e ) + { + d.TraceError( "*** Caught Exception: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + } +} diff --git a/src/tripwire/integritycheck.cpp b/src/tripwire/integritycheck.cpp new file mode 100644 index 0000000..fab0f44 --- /dev/null +++ b/src/tripwire/integritycheck.cpp @@ -0,0 +1,659 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// integritycheck.cpp +#include "stdtripwire.h" +#include "tripwirestrings.h" +#include "integritycheck.h" +#include "fco/twfactory.h" +#include "tw/fcoreport.h" +#include "core/error.h" +#include "core/debug.h" +#include "fco/fcocompare.h" +#include "tripwireutil.h" +#include "fco/fcopropset.h" +#include "fco/fcospec.h" +#include "fco/fcopropcalc.h" +#include "fco/fcospeclist.h" +#include "core/errorbucket.h" +#include "fco/fcodatasourceiter.h" + +// for verbose output +#include "core/usernotify.h" +#include "fco/fconametranslator.h" + +// +// TODO -- change the report interface so that it takes an error bucket instead of an error queue and then +// pass our error bucket to it. +// +// TODO -- we need to pass in the prop displayer and do ??? with it at the appropriate times... +// + +/////////////////////////////////////////////////////////////////////////////// +// ProcessAddedFCO +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::ProcessAddedFCO( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse ) +{ + ASSERT( pIter && (! pIter->Done()) ); + // + // don't do anything if this FCO is not a part of the spec... + // + if( mpCurSpec->ShouldStopDescent( pIter->GetName() ) ) + return; + // + // note that pIter points to the added fco + // + iFCO* pFCO = pIter->CreateFCO(); + mnObjectsScanned++; + mReportIter.SetObjectsScanned( mReportIter.GetObjectsScanned() + 1 ); + if( pFCO ) + { + cTripwireUtil::CalcProps( pFCO, mpCurSpec, mpPropCalc, 0 ); //TODO -- a property displayer should be passed in here. + mReportIter.GetAddedSet()->Insert( pFCO ); + pFCO->Release(); + // + // descend here, if we can... + // + if( bRecurse ) + { + if( pIter->CanDescend() ) + { + // note that we don't want to descend into the dbIter, so we will seek it + // to done... + // + while( ! dbIter.Done() ) dbIter.Next(); + std::auto_ptr pCopy( pIter->CreateCopy() ); + ProcessDir( dbIter, pCopy.get() ); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessRemovedFCO +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::ProcessRemovedFCO( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse ) +{ + ASSERT( ! dbIter.Done() ); + // + // don't do anything if this FCO is not a part of the spec... + // + if( mpCurSpec->ShouldStopDescent( dbIter.GetName() ) ) + return; + // + // we have to be careful here, since not all db nodes are guarenteed to have fco data associated with them. + // + if( dbIter.HasFCOData() ) + { + // add this to the "removed" set + // + iFCO* pFCO = dbIter.CreateFCO(); + mReportIter.GetRemovedSet()->Insert( pFCO ); + pFCO->Release(); + } + // descend if we can... + // + if( bRecurse ) + { + if( dbIter.CanDescend() ) + { + // we don't want pIter to be descended into, so we will pass null as the second param... + // + ProcessDir( dbIter, 0 ); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessChangedFCO +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::ProcessChangedFCO( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse ) +{ + ASSERT( pIter && (! pIter->Done()) ); + ASSERT( ! dbIter.Done() ); + cDebug d("cIntegrityCheck::ProcessChangedFCO"); + // + // don't do anything if this FCO is not a part of the spec... + // + if( mpCurSpec->ShouldStopDescent( pIter->GetName() ) ) + return; + + // if the database doesn't have this data, then process this as an add + // + if( ! dbIter.HasFCOData() ) + { + ProcessAddedFCO( dbIter, pIter, false ); // false means not to recurse + } + else + { + // here we will actually compare the two FCOs + // + TW_NOTIFY_VERBOSE( _T("--- %s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_CHECKING ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( pIter->GetName() ).c_str() ); + + iFCO* pNewFCO = pIter->CreateFCO(); + iFCO* pOldFCO = dbIter.CreateFCO(); + + mnObjectsScanned++; + mReportIter.SetObjectsScanned( mReportIter.GetObjectsScanned() + 1 ); + // + // if we can't create the operating system object, treat this as a removal; we will + // increment the os iterator... + // + if( ! pNewFCO ) + { + pIter->Next(); + ProcessRemovedFCO( dbIter, pIter, bRecurse ); + return; + } + + CompareFCOs( pOldFCO, pNewFCO ); + + //------------------------------------------------------------------------- + // Begin functionality necessary for policy update + // + bool bDbFCODirty = false; + // change the valid vector for the db's fco, if the appropriate flag is set + // + if( mFlags & FLAG_INVALIDATE_EXTRA_DB_PROPS ) + { + cFCOPropVector propsToInvalidate = pOldFCO->GetPropSet()->GetValidVector() & mpCurSpec->GetPropVector( pOldFCO ); + propsToInvalidate ^= pOldFCO->GetPropSet()->GetValidVector(); + pOldFCO->GetPropSet()->InvalidateProps( propsToInvalidate ); + + bDbFCODirty = true; + } + // update the old fco with the new properties... + // + if( mFlags & FLAG_SET_NEW_PROPS ) + { + cFCOPropVector propsToCopy = pOldFCO->GetPropSet()->GetValidVector() & pNewFCO->GetPropSet()->GetValidVector(); + propsToCopy ^= pNewFCO->GetPropSet()->GetValidVector(); + + pOldFCO->GetPropSet()->CopyProps( pNewFCO->GetPropSet(), propsToCopy ); + + bDbFCODirty = true; + } + // rewrite the fco to the database, if necessary + // + if( bDbFCODirty ) + { + dbIter.RemoveFCOData(); + dbIter.SetFCOData( pOldFCO ); + + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_DB_CHANGING ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( pOldFCO->GetName() ).c_str() ); + + } + // + // end policy update specific code + //------------------------------------------------------------------------- + + pNewFCO->Release(); + pOldFCO->Release(); + } + // + // finally, we need to recurse into our child directories... + // + if( bRecurse ) + { + if( pIter->CanDescend() || dbIter.CanDescend() ) + { + std::auto_ptr pCopy( pIter->CreateCopy() ); + ProcessDir( dbIter, pCopy.get() ); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// CompareFCOs +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::CompareFCOs( iFCO* pOldFCO, iFCO* pNewFCO ) +{ + cTripwireUtil::CalcProps( pNewFCO, mpCurSpec, mpPropCalc, 0 ); //TODO -- a property displayer should be passed in here. + // + // figure out what properties we are comparing...for an explanation of the propsToCheck derivation, see tripwire.cpp line 250. + // + cFCOPropVector propsToCheck; + if( mFlags & FLAG_COMPARE_VALID_PROPS_ONLY ) + { + propsToCheck = pOldFCO->GetPropSet()->GetValidVector() & + pNewFCO->GetPropSet()->GetValidVector(); + } + else + { + propsToCheck = pOldFCO->GetPropSet()->GetValidVector() | + pNewFCO->GetPropSet()->GetValidVector(); + } + propsToCheck &= mpCurSpec->GetPropVector( pNewFCO ); + // + // trim off the loose dir stuff... + // + if( (pOldFCO->GetCaps() & iFCO::CAP_CAN_HAVE_CHILDREN) && + (pNewFCO->GetCaps() & iFCO::CAP_CAN_HAVE_CHILDREN) ) + { + cFCOPropVector tmp = (propsToCheck ^ mLooseDirProps); + propsToCheck &= tmp; + } + // + // construct the compare object and actually do the compare + // + cFCOCompare compareObj( propsToCheck ); + uint32 result = compareObj.Compare(pOldFCO, pNewFCO); + + if( (result & cFCOCompare::PROPS_UNEQUAL) || (result & cFCOCompare::PROPS_NOT_ALL_VALID) ) + { + // this is a violation... + // + mReport.AddChangedFCO(mReportIter, pOldFCO, pNewFCO, compareObj.GetUnequalProps() | compareObj.GetInvalidProps()); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessDir +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::ProcessDir( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter ) +{ + cDebug d("cIntegrityCheck::ProcessDir"); + + // if either iterator is done, or if the data source iter is NULL, that indicates that the tree + // has stopped for that iterator, and all FCOs encountered by the other iter are all adds or removals, + // as appropriate. + // + // the first thing we will do is descend, if possible, and if not possible, set them to done(). + // + if( pIter ) + { + if( pIter->CanDescend() ) + { + pIter->Descend(); + } + else + { + pIter = 0; + } + } + if( ! dbIter.Done() ) + { + if( dbIter.CanDescend() ) + { + dbIter.Descend(); + } + else + { + while( ! dbIter.Done() ) dbIter.Next(); + } + } + // if they are both done, then we are done dealin'! + // + if( ((! pIter) || (pIter->Done())) && ( dbIter.Done() ) ) + { + //TODO -- what else do I need to do here? + return; + } + +#ifdef _DEBUG + if( dbIter.Done() ) + { + d.TraceDebug( "Processing directory %s\n", pIter->GetParentName().AsString().c_str() ); + } + else + { + d.TraceDebug( "Processing directory %s\n", dbIter.GetParentName().AsString().c_str() ); + } +#endif + + // + // now, process the entries in this directory... + // + while( true ) + { + // this just cleans up some logic statements below... + // + if( pIter && pIter->Done() ) + pIter = NULL; + + // if they are both done, then we are finished... + // + if( dbIter.Done() && (! pIter ) ) + break; + + if( dbIter.Done() ) + { + ASSERT( pIter != 0); + d.TraceDetail( "Examining and %s\n", pIter->GetName().AsString().c_str() ); + // + // these are all new entries, add them to the "Added" set... + // + ProcessAddedFCO( dbIter, pIter ); + pIter->Next(); + } + else if( ! pIter ) + { + ASSERT( ! dbIter.Done() ); + d.TraceDetail( _T("--Examining %s and \n"), dbIter.GetName().AsString().c_str() ); + // + // these are all removed objects. + // + ProcessRemovedFCO( dbIter, pIter ); + dbIter.Next(); + } + else + { + d.TraceDetail( _T("--Examining %s and %s\n"), dbIter.GetName().AsString().c_str(), pIter->GetName().AsString().c_str() ); + + ASSERT( pIter->GetParentName() == dbIter.GetParentName() ); + // + // get the relationship between the current nodes of the two iterators... + // + iFCODataSourceIter::Relationship rel = dbIter.GetRelationship( *pIter ); + // + // if rel == LT, then the old has something the new doesn't (ie -- a removal!) + // if rel == GT, then there is an addition + // + if( rel == iFCODataSourceIter::REL_LT ) + { + ProcessRemovedFCO( dbIter, pIter ); + dbIter.Next(); + } + else if( rel == iFCODataSourceIter::REL_GT ) + { + ProcessAddedFCO( dbIter, pIter ); + pIter->Next(); + + } + else + { + // we actually have to compare the FCOs at this point... + // NOTE -- if the db iter has no data, then this is an add again. + // + ProcessChangedFCO( dbIter, pIter ); + + dbIter.Next(); + pIter->Next(); + } + + ASSERT( pIter->GetParentName() == dbIter.GetParentName() ); + } + } + d.TraceDebug( "Done Processing Directory\n"); +} + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cIntegrityCheck::cIntegrityCheck(cGenre::Genre genreNum, const cFCOSpecList& specList, cHierDatabase& db, cFCOReport& report, cErrorBucket* pBucket ) +: + mGenre ( genreNum ), + mSpecList ( specList ), + mDb ( db ), + mReport ( report ), + mpPropCalc ( iTWFactory::GetInstance()->CreatePropCalc() ), + mpCurSpec ( 0 ), + mReportIter ( report, genreNum ), + mFlags ( 0 ), + mnObjectsScanned( 0 ) +{ + // mBucket is a pass-thru bucket; its only job is to pass the errors onto its child. + // + mBucket.SetChild ( pBucket ); + mpPropCalc->SetErrorBucket ( &mBucket ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cIntegrityCheck::~cIntegrityCheck() +{ + delete mpPropCalc; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::Execute( uint32 flags ) +{ + mFlags = flags; + // create the data source iterator + // + std::auto_ptr pDSIter(iTWFactory::GetInstance()->CreateDataSourceIter()); + // + // set up the database's iterator... + // I assume the current genre is correct... + // + cDbDataSourceIter dbIter( &mDb ); + + // + // set the iterator's error bucket... + // + pDSIter->SetErrorBucket(&mBucket); + dbIter.SetErrorBucket(&mBucket); + + // + // set up loose directories; note that mLooseDirProps represents properties that will + // be removed from the ones used to compare, so if loose dirs is not specified, we can set this + // to the empty vector. + // + if( flags & FLAG_LOOSE_DIR ) + { + mLooseDirProps = iTWFactory::GetInstance()->GetLooseDirMask(); + } + + // + // set up flags for the property calculator and iterators + // + if( flags & FLAG_ERASE_FOOTPRINTS_IC ) + { + mpPropCalc->SetCalcFlags( iFCOPropCalc::DO_NOT_MODIFY_PROPERTIES ); + dbIter.SetIterFlags ( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + pDSIter->SetIterFlags ( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + } + + // + // iterate over all of the specs... + // + cFCOSpecListCanonicalIter specIter(mSpecList); + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + mpCurSpec = specIter.Spec(); + + // verbose output + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_CHECKING_RULE ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( mpCurSpec->GetStartPoint() ).c_str() ); + // + // add the spec to the report... + // + mReport.AddSpec(mGenre, mpCurSpec, specIter.Attr(), &mReportIter); + ASSERT(! mReportIter.Done()); + // + // associate the error bucket to this current spec in the report + // + mReportIter.GetErrorQueue()->SetChild( mBucket.GetChild() ); + mBucket.SetChild( mReportIter.GetErrorQueue() ); + // + // seek each iterator to the appropriate starting point... + // + dbIter.SeekToFCO ( mpCurSpec->GetStartPoint(), false ); // false means not to create my peers + pDSIter->SeekToFCO ( mpCurSpec->GetStartPoint(), false ); + // + // integrity check the start point; note that the ProcessXXX functions will + // handle recursing into the subdirectories and stopping when the spec says to + // + if( dbIter.Done() && pDSIter->Done() ) + { + // nothing to do here... + ; + } + else if( pDSIter->Done() ) + { + // removed object... + ProcessRemovedFCO( dbIter, pDSIter.get() ); + } + else if( dbIter.Done() ) + { + // added object... + ProcessAddedFCO( dbIter, pDSIter.get() ); + } + else + { + // possible changed fco + ProcessChangedFCO( dbIter, pDSIter.get() ); + } + + // dissociate the report error bucket and mine... + // + mBucket.SetChild( mReportIter.GetErrorQueue()->GetChild() ); + mReportIter.GetErrorQueue()->SetChild( 0 ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ExecuteOnObjectList +/////////////////////////////////////////////////////////////////////////////// +void cIntegrityCheck::ExecuteOnObjectList( const std::list& fcoNames, uint32 flags ) +{ + iFCONameTranslator* pTrans = iTWFactory::GetInstance()->GetNameTranslator(); + // + // create the data source iterator + // + std::auto_ptr pDSIter(iTWFactory::GetInstance()->CreateDataSourceIter()); + // + // set up the database's iterator... + // I assume the current genre is correct... + // + cDbDataSourceIter dbIter ( &mDb ); + cFCOSpecListCanonicalIter specIter(mSpecList); + + // + // set the iterators' error bucket... + // + pDSIter->SetErrorBucket(&mBucket); + dbIter.SetErrorBucket(&mBucket); + + // + // set up flags for the property calculator and iterators + // + if( flags & FLAG_ERASE_FOOTPRINTS_IC ) + { + mpPropCalc->SetCalcFlags( iFCOPropCalc::DO_NOT_MODIFY_PROPERTIES ); + dbIter.SetIterFlags ( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + pDSIter->SetIterFlags ( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + } + + // + // iterate over all the objects to integrity check.. + // + std::list::const_iterator it; + for( it = fcoNames.begin(); it != fcoNames.end(); it++ ) + { + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_CHECKING ).c_str(), + pTrans->ToStringDisplay( *it ).c_str() ); + // + // figure out which spec this fco belongs in... + // + for( specIter.SeekBegin(); ! specIter.Done(); specIter.Next() ) + { + if( specIter.Spec()->SpecContainsFCO( *it ) ) + break; + } + // error if we found no spec. + // + if( specIter.Done() ) + { + mBucket.AddError ( eICFCONotInSpec( pTrans->ToStringDisplay( *it ) ) ); + mReport.GetErrorQueue()->cErrorBucket::AddError ( eICFCONotInSpec( pTrans->ToStringDisplay( *it ) ) ); + continue; + } + mpCurSpec = specIter.Spec(); + // + // add this spec to the report if it is not there + // and seek to the spec + // + if( ! mReportIter.SeekToSpec( mpCurSpec ) ) + { + mReport.AddSpec(mGenre, mpCurSpec, specIter.Attr(), &mReportIter); + } + // insert the report error bucket between mpErrorBucket and its children... + // + mReportIter.GetErrorQueue()->SetChild( mBucket.GetChild() ); + mBucket.SetChild( mReportIter.GetErrorQueue() ); + // + // create the fco in the database... + // + dbIter.SeekToFCO( *it, false ); + if( dbIter.Done() || (! dbIter.HasFCOData()) ) + { + // fco not found in the db! + // + mBucket.AddError( eICFCONotInDb( pTrans->ToStringDisplay( *it ) ) ); + } + else + { + iFCO* pOldFCO = dbIter.CreateFCO(); + // + // create the fco from the data source + // + pDSIter->SeekToFCO ( *it, false ); + if( ! pDSIter->Done() ) + { + iFCO* pNewFCO = pDSIter->CreateFCO(); + mnObjectsScanned++; + mReportIter.SetObjectsScanned( mReportIter.GetObjectsScanned() + 1 ); + + if( pNewFCO ) + { + CompareFCOs( pOldFCO, pNewFCO ); + pNewFCO->Release(); + } + else + { + mBucket.AddError( eICFCOCreate( pTrans->ToStringDisplay( *it ) ) ); + } + } + pOldFCO->Release(); + } + // dissociate the report error bucket and mine... + // + mBucket.SetChild( mReportIter.GetErrorQueue()->GetChild() ); + mReportIter.GetErrorQueue()->SetChild( 0 ); + } + +} + diff --git a/src/tripwire/integritycheck.h b/src/tripwire/integritycheck.h new file mode 100644 index 0000000..e19d05e --- /dev/null +++ b/src/tripwire/integritycheck.h @@ -0,0 +1,141 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// integritycheck.h +// +#ifndef __INTEGRITYCHECK_H +#define __INTEGRITYCHECK_H + +#ifndef __DBDATASOURCE_H +#include "tw/dbdatasource.h" +#endif +#ifndef __FCOREPORT_H +#include "tw/fcoreport.h" +#endif +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif +#ifndef __ERRORBUCKETIMPL_H +#include "core/errorbucketimpl.h" +#endif +#ifndef __FCOPROPVECTOR_H +#include "fco/fcopropvector.h" +#endif + +class cFCOSpecList; +class cHierDatabase; +class cFCOReport; +class cErrorBucket; +class iFCODataSourceIter; +class iFCOSpec; +class cFCOReportSpecIter; +class iFCOPropCalc; + +TSS_EXCEPTION( eIC, eError ); +TSS_EXCEPTION( eICFCONotInSpec, eIC ); +TSS_EXCEPTION( eICFCONotInDb, eIC ); +TSS_EXCEPTION( eICFCOCreate, eIC ); +TSS_EXCEPTION( eICBadPol, eIC ); +TSS_EXCEPTION( eICUnknownGenre, eIC ); +TSS_EXCEPTION( eICBadSevVal, eIC ); +TSS_EXCEPTION( eICInappropriateGenre, eIC ); +TSS_EXCEPTION( eICDifferentUsers, eIC ); +TSS_EXCEPTION( eICMismatchingParams, eIC ); + + +class cIntegrityCheck +{ +public: + cIntegrityCheck( cGenre::Genre genreNum, const cFCOSpecList& specList, + cHierDatabase& db, cFCOReport& report, cErrorBucket* pBucket ); + // if this is an integrity check of a set of files (instead of a policy file based check) + // then specList refers to the db's spec list. Otherwise, it represents the spec list being + // checked. NOTE -- this class has no way to decide if the specList is appropriate for the database + // or not, so it is the client's responsibility to do this. + + ~cIntegrityCheck(); + + void Execute( uint32 flags = 0 ); + // flags should be 0, or some combination of the below enumeration + // TODO -- specify what kinds of exception can come up from here.... + void ExecuteOnObjectList( const std::list& fcoNames, uint32 flags = 0 ); + // executes an integrity check on the objects named in the list. The specList passed in + // as the first parameter to the ctor is interprited as the db's spec list. + int ObjectsScanned() { return mnObjectsScanned; }; + + enum Flags + { + FLAG_LOOSE_DIR = 0x00000001, + // when this is set, fcos whose caps return CAP_CAN_HAVE_CHILDREN will not + // compare any properties that are returned from iTWFactory::GetLooseDirMask() + FLAG_COMPARE_VALID_PROPS_ONLY = 0x00000002, + // when this is set, only the properties that are valid in both FCOs being + // compared are compared. + FLAG_INVALIDATE_EXTRA_DB_PROPS = 0x00000004, + // used by policy update; this flag indicates that we should invalidate properties + // of objects in the database that are not a part of the spec used to compare the object. + // Note: it is kind of a hack that this is here; in a perfect design, integrity check + // would never modify the database -- 8 feb 99 mdb + FLAG_SET_NEW_PROPS = 0x00000008, + // also used exclusively in policy update, this is an even bigger and even sicker hack than the + // previous enumeration. This flag indicates that any valid properties in the new FCO during + // an integrity check that are not valid in the database FCO should be copied to the db's fco. + // Yuck! + FLAG_ERASE_FOOTPRINTS_IC = 0x00000010 + // when this flag is set, IC will attempt to leave no footprints when doing an integrity check. + // for instance, IC will tell the property calculator to reset access times. + }; + +private: + cGenre::Genre mGenre; + const cFCOSpecList& mSpecList; + cHierDatabase& mDb; + cFCOReport& mReport; + cErrorBucketPassThru mBucket; + iFCOPropCalc* mpPropCalc; + iFCOSpec* mpCurSpec; // the spec we are currently operating on + cFCOReportSpecIter mReportIter; // the current iterator into the report + cFCOPropVector mLooseDirProps; // properties that should be ignored in loose directories + uint32 mFlags; // flags passed in to execute() + int mnObjectsScanned; // number of objects scanned in system ( scanning includes + // discovering that an FCO does not exist ) + + void ProcessDir ( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter ); + void ProcessAddedFCO ( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse = true ); + void ProcessRemovedFCO ( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse = true ); + void ProcessChangedFCO ( cDbDataSourceIter dbIter, iFCODataSourceIter* pIter, bool bRecurse = true ); + void CompareFCOs ( iFCO* pOldFCO, iFCO* pNewFCO ); +}; + + +#endif //__INTEGRITYCHECK_H + diff --git a/src/tripwire/integritycheck_t.cpp b/src/tripwire/integritycheck_t.cpp new file mode 100644 index 0000000..d8d85a5 --- /dev/null +++ b/src/tripwire/integritycheck_t.cpp @@ -0,0 +1,99 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// integritycheck_t.cpp + +#include "stdtripwire.h" +#include "integritycheck.h" + +#include "generatedb.h" +#include "core/fsservices.h" +#include "core/debug.h" +#include "core/errorbucketimpl.h" +#include "fco/fcospecimpl.h" +#include "fco/fcospeclist.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "db/hierdatabase.h" +#include "parser/policyparser.h" +#include "test/test.h" +#include "tw/textreportviewer.h" + + +#include + +void TestIntegrityCheck() +{ + cDebug d("TestIntegrityCheck"); + + try + { + cFCOReport report; + cGenreSpecListVector slv; + cErrorTracer et; + iFCONameInfo* pInfo = iTWFactory::GetInstance()->GetNameInfo(); + cHierDatabase db( pInfo->IsCaseSensitive(), pInfo->GetDelimitingChar() ); + db.Open( _T("c:/tmp/tw.db"), 5, false ); + // + // make some specs... + // + std::ifstream in; + in.open("c:/tmp/pol.pol"); + if(in.fail()) + { + d.TraceError( "Unable to open policy file!\n" ); + TEST( false ); + return; + } + cPolicyParser parser(in); + parser.Execute(slv, &et); + + // + // ok, time to integrity check! + // + cGenreSpecListVector::iterator at; + for( at = slv.begin(); at != slv.end(); at++ ) + { + cIntegrityCheck ic( at->GetGenre(), at->GetSpecList(), db, report, &et ); + ic.Execute(); + } + + // + // finally, let's print out the report... + // + report.TraceContents(); + + } + catch( eError& e ) + { + d.TraceError( "*** Caught Exception: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + } +} diff --git a/src/tripwire/mailmessage.cpp b/src/tripwire/mailmessage.cpp new file mode 100644 index 0000000..d2dfa0c --- /dev/null +++ b/src/tripwire/mailmessage.cpp @@ -0,0 +1,886 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtripwire.h" +#include "core/debug.h" +#include "mailmessage.h" +#include +#include "core/stringutil.h" +#include "core/timeconvert.h" +#include "tw/systeminfo.h" +#include "core/file.h" +#include "core/ntmbs.h" + + +/////////////////////////////////////////////////////////////////////////////// +cMailMessage::cMailMessage() +{ +} + + +/////////////////////////////////////////////////////////////////////////////// +cMailMessage::~cMailMessage() +{ +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::SetBody(const TSTRING& strBody) +{ + mstrBody = strBody; +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::SetFrom(const TSTRING& strFrom) +{ + mstrFrom = strFrom; +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::SetFromName(const TSTRING& strFromName) +{ + mstrFromName = strFromName; +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::SetSubject(const TSTRING& strSubject) +{ + mstrSubject = strSubject; +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::AddRecipient(const TSTRING& strRecipient) +{ + mvstrRecipients.push_back(strRecipient); +} + + +/////////////////////////////////////////////////////////////////////////////// +void cMailMessage::AttachFile(const TSTRING& strFullPath) +{ + mvstrAttachments.push_back(strFullPath); +} + + +/////////////////////////////////////////////////////////////////////////////// +bool cMailMessage::Send() +{ + // this is a pure virtual method. You should never end up here. + ASSERT(false); + return false; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Returns true if enough things have been set so that a useful email message can be sent +// +bool cMailMessage::Ready() +{ + // You must specify 'from', 'to', the subject + if( mstrFrom.length() == 0 || mvstrRecipients.size() == 0 || mstrSubject.length() == 0 ) + { + return false; + } + + // make sure we can at least send something... + if( mstrBody.empty() ) + { + mstrBody = _T("\r\n"); + } + + return true; +} + +bool cMailMessage::GetAttachmentsAsString( std::string& s ) +{ + s.erase(); + bool allOK = true; + for( std::vector::const_iterator at = mvstrAttachments.begin(); + at != mvstrAttachments.end(); + at++ ) + { + s += "\r\n"; + + cFile file; + try + { + file.Open( at->c_str(), cFile::OPEN_READ); + + + // Simply stream the file into the socket. + // This will append the file as additional text. + const cFile::File_t cBufSize = 2048; + char buf[cBufSize]; + cFile::File_t bytes; + + while ((bytes = file.Read(buf, cBufSize)) != 0) + { + ASSERT( bytes > 0 && bytes <= cBufSize ); // ensures typecast below + ASSERT( (std::string::size_type)bytes < std::string().max_size() ); + + s += std::string( buf, (size_t)bytes ); + } + + file.Close(); + } + catch (eFile&) + { + // TODO: There is no method of reporting detailed information on + // errors if they occur. Perhaps someday there will be. At the moment + // it does not seem necessary as the only attached files that will + // be sent are temporary files that tripwire has just created. Thus + // the likelyhood of failure is low. + file.Close(); + allOK = false; + } + } + + // Send a new line to be sure the file ends properly + // Failure to do this could result in the "." begin acknowledged as + // the end of the email message. + s += "\r\n"; + + return allOK; +} + +std::string cMailMessage::Create822Header() +{ + std::ostringstream ss; + std::string strToList; + for( std::vector< TSTRING >::size_type i = 0; + i < mvstrRecipients.size(); + i++ ) + { + if( strToList.length() > 0 ) + strToList += ", "; + + strToList += cStringUtil::TstrToStr( mvstrRecipients[i] ); + } + + ss << cMailMessageUtil::FormatAddressHeader( "MIME-Version", "1.0" ); + + TSTRING strDate; + if( cMailMessageUtil::ReadDate( strDate ) ) + ss << cMailMessageUtil::FormatAddressHeader( "Date", cStringUtil::TstrToStr( strDate ) ); + + std::string fromAddress; + if( ! mstrFromName.empty() ) + { + fromAddress = "\""; + fromAddress += cStringUtil::TstrToStr(mstrFromName); + fromAddress += "\" <"; + fromAddress += cStringUtil::TstrToStr(mstrFrom); + fromAddress += ">"; + } + else + { + fromAddress = cStringUtil::TstrToStr(mstrFrom); + } + + ss << cMailMessageUtil::FormatAddressHeader( "From", fromAddress); + ss << cMailMessageUtil::FormatAddressHeader( "To", strToList ); + ss << cMailMessageUtil::FormatNonAddressHeader( "Subject", cStringUtil::TstrToStr(mstrSubject) ); + ss << cMailMessageUtil::FormatAddressHeader( "Content-Type", "text/plain" ); + + return ss.str(); +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// cMailMessageUtil +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// gets the date in the RFC822 compliant form "Tue, 16 Mar 1999 10:53:17 -0800 (PST)" +// TODO:BAM -- make windows and unix use same function +bool cMailMessageUtil::ReadDate( TSTRING& strDateBuf ) +{ + bool fGotDate = false; + +#if HAVE_STRFTIME + + TCHAR szDate[1024]; + struct tm *tm = NULL; + + time_t current_time = time(NULL); + tm = localtime ( ¤t_time ); + + const TCHAR* szFormat = _T("%a, %d %b %Y %H:%M:%S %z"); + + size_t numChars = _tcsftime( szDate, countof( szDate ), szFormat, tm ); + + if ( numChars != 0 ) + { + strDateBuf = szDate; + fGotDate = true; + } + +#else + + int64 now = cSystemInfo::GetExeStartTime(); + strDateBuf = cTimeUtil::GetRFC822Date(cTimeUtil::TimeToDateGMT(now)); + fGotDate = true; + +#endif // HAVE_STRFTIME + + return fGotDate; +} + + +static char* util_Get_IANA_CharSet() +{ + const char* pCP = setlocale( LC_CTYPE, NULL ); + + if( pCP && pCP[0] ) + { + std::string s = pCP; + // TODO:BAM -- change this to ctype::tolower when all compilers + // have a proper locale impl. or better yet move to core/twlocale.cpp + std::transform( s.begin(), s.end(), s.begin(), tolower ); + if( std::string::npos != s.find( "jp" ) || + std::string::npos != s.find( "jap" ) ) + { + return "ISO-2022-JP"; + } + } + + // default + return "US-ASCII"; + +} + + +static +bool +NeedsEncoding( char ch ) +{ + return( ( ch < 33 ) || + ( ch > 60 && ch < 62 ) || + ( ch > 126 ) ); +} + +static +std::string +EncodeChar( char ch ) +{ + std::ostringstream ss; + + ss.imbue( std::locale::classic() ); + ss.fill( '0' ); + ss.setf( std::ios_base::hex, std::ios_base::basefield ); + ss.width( 2 ); + + ss << (unsigned int)(unsigned char)ch; + + ASSERT( ss.str().length() == 2 ); + + // Make sure the hex is uppercase + std::string s = ss.str(); + std::transform( s.begin(), s.end(), s.begin(), toupper ); + + return s; +} + + +/* static */ +iMimeEncoding* iMimeEncoding::GetInstance() +{ +#define TSS_USE_QUOTED_PRINTABLE_MIME + + static iMimeEncoding* pME= + + #if defined( TSS_USE_BASE64_MIME ) + new cBase64Encoding; + #elif defined( TSS_USE_QUOTED_PRINTABLE_MIME ) + new cQuotedPrintableEncoding; + #else + #error what is iMimeEncoding? + #endif + + return pME; +} + +// TODO:BAM -- line breaks +// TODO:BAM -- ToEncoding( const std::string& sIn, int maxLineLen = -1, int maxLen = -1 ) +std::string +cQuotedPrintableEncoding::Encode( const std::string& sIn, + int maxLineLen, + int maxLen ) +{ + static const size_t _CHAR_AS_HEX_LEN = 2; + static const size_t _ENCODED_CHAR_LEN = _CHAR_AS_HEX_LEN + sizeof( '=' ); + + std::string sOut; + sOut.resize( sIn.size() * _ENCODED_CHAR_LEN ); // optimize. one char can turn into 3 + + std::string::const_iterator at; + std::string::size_type i = 0; + std::string::size_type lineLen = 0; + for( at = sIn.begin(); + at != sIn.end(); + at++, lineLen += _ENCODED_CHAR_LEN ) + { + if( NeedsEncoding( *at ) ) + { + ASSERT( (unsigned char)*at <= 0xFF ); + + std::string sTmp = EncodeChar( *at ); + ASSERT( sTmp.length() == _CHAR_AS_HEX_LEN ); + + sOut[i++] = '='; + + std::copy( &sTmp[0], &sTmp[_CHAR_AS_HEX_LEN], &sOut[i] ); + ASSERT( _CHAR_AS_HEX_LEN > 0 ); + i += _CHAR_AS_HEX_LEN; + } + else + { + sOut[i++] = *at; + } + + // + // if string is too long, just quit + // + if( maxLen != -1 && i >= maxLen - _ENCODED_CHAR_LEN ) + { + break; + } + + // + // check line len + // + if( maxLineLen != -1 && lineLen >= maxLineLen - _ENCODED_CHAR_LEN ) + { + // append EOL + sOut[i++] = '='; + sOut[i++] = '\r'; + sOut[i++] = '\n'; + lineLen = 0; + } + } + + sOut.resize( i ); + + return sOut; +} + +std::string cMailMessageUtil::CreateEncodedText( const std::string& text ) +{ + cDebug d("cMailMessageUtil::CreateEncodedText"); + + d.TraceDebug( "came in as: %s\n", text.c_str() ); + + std::string s; + + + s += "=?"; + s += util_Get_IANA_CharSet(); + + s += "?"; + s += iMimeEncoding::GetInstance()->GetEncodedWordIdentifier(); + s += "?"; + s += iMimeEncoding::GetInstance()->Encode( text, -1, _MAX_RFC822_HEADER_LEN ); + s += "?="; + + ASSERT( s.length() < _MAX_RFC822_LINE_LEN - _EOL_LEN ); + + d.TraceDebug( "came out as: %s\n", s.c_str() ); + + return s; +} + +// TODO:BAM -- note that address headers can only have usascii chars +// TODO:BAM -- lines can only be 76 chars long -- enforce that! +std::string cMailMessageUtil::FormatAddressHeader( const std::string& name, const std::string& addr ) +{ + cDebug d("cMailMessageUtil::FormatAddressHeader"); + + d.TraceDebug( "name: %s, value: %s\n", name.c_str(), addr.c_str() ); + + std::string s; + + s += name; + s += ": "; + s += addr; + s += "\r\n"; + + d.TraceDebug( "came out as: %s\n", s.c_str() ); + + return s; +} + +// TODO:BAM -- lines can only be 76 chars long -- enforce that! +std::string cMailMessageUtil::FormatNonAddressHeader( const std::string& name, const std::string& valC ) +{ + cDebug d("cMailMessageUtil::FormatNonAddressHeader"); + + d.TraceDebug( "name: %s, value: %s\n", name.c_str(), valC.c_str() ); + + std::string val = valC; + ASSERT( val != "To" ); + ASSERT( val != "From" ); + ASSERT( val != "Sender" ); + ASSERT( val != "cc" ); + ASSERT( val != "bcc" ); + // ... + + std::string s; + + s += name; + s += ": "; + + if( HasNonAsciiChars( val ) ) + s += CreateEncodedText( val ); + else + s += val; + + s += "\r\n"; + + + d.TraceDebug( "came out as: %s\n", s.c_str() ); + + ASSERT( s.length() < _MAX_RFC822_LINE_LEN - _EOL_LEN ); + + return s; +} + + +bool +cMailMessageUtil::HasNonAsciiChars( const std::string& s ) +{ + for( std::string::const_iterator at = s.begin(); + at != s.end(); + at ++ ) + { + if( (unsigned char)*at > (unsigned char)0x7F ) + return true; + } + + return false; +} + +// converts lone \n's to \r\n +std::string& cMailMessageUtil::LFToCRLF( std::string& sIn ) +{ + cDebug d("cMailMessageUtil::LFToCRLF"); + + if( sIn.empty() ) + return sIn; + + std::string sOut; + + // worst case: could be just '\n's + // in which case we'd double the length + sOut.resize( sIn.size() * 2 ); + + bool lastCharCR = false; + + std::string::size_type stringSize = 0; + std::string::const_iterator at; + std::string::difference_type charSize; + for( at = sIn.begin(), charSize = ( (*at ? at+1 : at) - at ); + at != sIn.end(); + at += charSize, charSize = ( (*at ? at+1 : at) - at ) ) + { + ASSERT( charSize > 0 ); + + if( *at == '\n' ) + { + if( ! lastCharCR ) + { + d.TraceDebug( "Adding LF\n"); + sOut[stringSize++] = '\r'; + } + + lastCharCR = false; + } + else if( *at == '\r') + { + lastCharCR = true; + } + else + { + lastCharCR = false; + } + + std::copy( at, at + charSize, &sOut[stringSize] ); + stringSize += charSize; + } + + sOut.resize( stringSize ); + sIn = sOut; + return sIn; +} + + +// #define RDIFALCO_BASE64_IMPLEMENTATION +#ifndef RDIFALCO_BASE64_IMPLEMENTATION +/* +static +std::string +util_Base64Encode( const byte b[3], int size ) +{ + // TODO:BAM -- what about endianness? + ASSERT( size > 0 && size <= 3 ); + static char v64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string s; + + if( size >= 1 ) + { + // encode A + s += v64[ b[0] >> 2 ]; + } + + if( size >= 2 ) + { + // encode B,C + s += v64[ ( ( b[0] & (byte)0x3 ) << 4 ) | ( b[1] >> 4 ) ]; + + if( size == 3 ) + s += v64[ ( ( b[1] & (byte)0xF ) << 2 ) | ( b[2] >> 6 ) ]; + else + s += v64[ ( ( b[1] & (byte)0xF ) << 2 ) ]; + } + + if( size >= 3 ) + { + // encode D + s += v64[ b[2] & (byte)0x3F ]; + } + + // padding + if( size == 1 ) + s += "=="; + else if( size == 2 ) + s += "="; + + return s; +} + +// MS _defines_ 'min' and 'max', so I can't use std::min(). +template< class T > +const T& MS_SUCKS_min( const T& a, const T& b ) +{ + return( b < a ? b : a ); +} + + +/// More consistent with the rest of our Convert interfaces + +// NOTE: Works when we don't want to allocate anything new + +const std::string::value_type* +cMailMessageUtil::ConvertBase64( + std::string& sEncode, + const byte* pchSrc, + size_t nchSrc ) +{ + sEncode.assign( ToBase64( pchSrc, nchSrc ) ); + return sEncode.c_str(); +} + + +std::string +cMailMessageUtil::ToBase64( const byte* p, size_t size ) +{ + ASSERT( sizeof( uint8 ) == sizeof( byte ) ); // everything breaks otherwise + std::string s; + + const int MAX_WORKING_BYTES = 3; + const int CHARS_PER_WORKING_BYTES = 4; + const int MAX_CHARS_PER_BYTE = 2; // should be + ASSERT( MAX_CHARS_PER_BYTE > CHARS_PER_WORKING_BYTES/MAX_WORKING_BYTES ); + const int NERVOUS_LINE_BUFFER = 10; + const byte* at = p; + byte buf[ MAX_WORKING_BYTES ]; + int nbLeft; + int nbWorking; + int nchCurLine; + std::string::size_type i = 0; // where we are in the output string + + s.resize( size * MAX_CHARS_PER_BYTE ); + + + for ( + nchCurLine = 0, nbLeft = size, nbWorking = MS_SUCKS_min( MAX_WORKING_BYTES, nbLeft ); + nbLeft > 0; + nchCurLine += CHARS_PER_WORKING_BYTES, at += nbWorking, nbLeft -= nbWorking, nbWorking = MS_SUCKS_min( MAX_WORKING_BYTES, nbLeft ) + ) + { + ASSERT( nbWorking > 0 ); + + // fill out the working buffer + std::copy( at, at + nbWorking, &buf[0] ); + + // encode from working buffer to 'enc' string + std::string enc = util_Base64Encode( buf, nbWorking ); + + // append 'enc' string to output string + for( std::string::const_iterator at = enc.begin(); + at != enc.end(); + at++ ) + { + s[i++] = *at; + } + + // make sure we aren't over the max line length + if( nchCurLine > ( _MAX_RFC822_LINE_LEN - NERVOUS_LINE_BUFFER ) ) // NERVOUS_LINE_BUFFER for a little margin of error + { + s[i++] = '\r'; + s[i++] = '\n'; + nchCurLine = 0; + } + } + + s.resize( i ); + return s; +} +*/ +#else//RDIFALCO_BASE64_IMPLEMENTATION + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// RAD:10311999 -- A Different Try +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +namespace /*Unique*/ +{ + typedef byte byte_t; + +#ifdef TSS_MAKE_EOL_CRLF + const byte _aszEoL[] = "\r\n"; + size_t _EOL_LEN = 2; + +#else + const byte _aszEoL[] = "\n"; + size_t _EOL_LEN = 1; + +#endif + + const byte_t _abBase64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + inline + size_t + tss_base64_amplitude() // TODO: Make a Constant + { + /* + * NOTE:RAD -- Calculate Max Incoming Bytes: + * + * eol_bytes = ( UINT_MAX / _MAX_RFC822_LINE_LEN ) * _EOL_LEN; + * max_bytes = UINT_MAX - eol_bytes; + * cvt_bytes = max_bytes / 4 * 3; + */ + return (((UINT_MAX - (UINT_MAX / _MAX_RFC822_LINE_LEN * _EOL_LEN)) / 4) * 3) + 1; + } + + inline + size_t + tss_encode_base64_size( size_t nchSource ) + { + ASSERT( nchSource < tss_base64_amplitude() ); // NOTE: + + /* NOTE: The formula is -- + + bring source bytes to an even divisible of 3 (the padding bytes) + + number of source bytes to converted (3:4 conversion ratio) + + ( number of lines ) * ( size of end of line string ) */ + + size_t nchPadding = nchSource % 3; + size_t nchOut = ((nchSource + nchPadding) / 3) * 4; + size_t nchEol = (nchOut / (_MAX_RFC822_LINE_LEN - _EOL_LEN)) * _EOL_LEN; + + return nchOut + nchEol + 2; + } + + void + tss_encode_digit_base64( + const byte_t*& pchSrc, size_t& nchSrcLeft, + byte_t*& pchBuf, size_t& nchBufLeft ) + { + // NOTE:RAD -- Redundant and ugly but very fast!! + + ASSERT( nchBufLeft > 4 ); // One for NULL + + switch ( nchSrcLeft ) + { + case 0: + { + ASSERTMSG( false, "Invalid call to encode_base64_digit!" ); + break; + } + case 1: + { + int ch1 = int( *pchSrc++ & 0xFF ); + + *pchBuf++ = _abBase64[ (ch1 & 0xFC) >> 2 ]; + *pchBuf++ = _abBase64[ (ch1 & 0x03) << 4 ]; + *pchBuf++ = '='; + *pchBuf++ = '='; + + nchSrcLeft = 0; // NOTE: + break; + } + case 2: + { + int ch1 = int( *pchSrc++ & 0xFF ); + int ch2 = int( *pchSrc++ & 0xFF ); + + *pchBuf++ = _abBase64[ ( (ch1 & 0xFC) >> 2 ) ]; + *pchBuf++ = _abBase64[ ( (ch1 & 0x03) << 4 ) | ( (ch2 & 0xF0) >> 4 ) ]; + *pchBuf++ = _abBase64[ ( (ch2 & 0x0F) << 2 ) ]; + *pchBuf++ = '='; + + nchSrcLeft = 0; // NOTE: + break; + } + default: + { + + int ch1 = int( *pchSrc++ & 0xFF ); + int ch2 = int( *pchSrc++ & 0xFF ); + int ch3 = int( *pchSrc++ & 0xFF ); + + *pchBuf++ = _abBase64[ ( (ch1 & 0xFC) >> 2 ) ]; + *pchBuf++ = _abBase64[ ( (ch1 & 0x03) << 4 ) | ( (ch2 & 0xF0) >> 4 ) ]; + *pchBuf++ = _abBase64[ ( (ch2 & 0x0F) << 2 ) | ( (ch3 & 0xC0) >> 6 ) ]; + *pchBuf++ = _abBase64[ ( ch3 & 0x3F ) ]; + + nchSrcLeft -= 3; // NOTE: Probably greater than 3 + break; + } + } + + nchBufLeft -= 4; // Always the same due to padding! + }; + + + size_t + tss_encode_base64( + const byte_t* pchSource, size_t nchSource, + byte_t* pchBuffer, size_t nchBuffer ) + { + const size_t _ERROR = std::string::npos; // -1; + + + //--Assert Preconditions + + if ( pchSource == 0 || nchSource == 0 ) + return _ERROR; + + + //--If pchBuffer == 0, User is requesting Size + + size_t nchBuf = tss_encode_base64_size( nchSource ); + + if ( pchBuffer == 0 ) // Requesting Size + return nchBuf; + + if ( nchBuf > nchBuffer ) // DOH!! + return _ERROR; + + + //--Get three characters at a time and encode them (watching linelen) + + byte_t* pchBuf = ( pchBuffer + 0 ); + const byte_t* pchSrc = ( pchSource + 0 ); + + + const size_t _max_linelen = ( _MAX_RFC822_LINE_LEN - _EOL_LEN ); + size_t nLineLen = 0; + + for ( ; nchSource; ) + { + // Like iconv: Increment pointers and decrement sizes + tss_encode_digit_base64( pchSrc, nchSource, pchBuf, nchBuf ); + + nLineLen += 4; + + if ( nchSource == 0 || nLineLen > _max_linelen ) + { + nLineLen = 0; // RESET: + + const byte_t* pchEol = &_aszEoL[0]; + while ( *pchEol ) + *pchBuf++ = *pchEol++; + } + } + + *pchBuf = 0x00; // CAUTION: Null Terminate!!! + + return ( pchBuf - pchBuffer ); + } +}//Unique:: + + +const std::string::value_type* +cMailMessageUtil::ConvertBase64( + std::string& sEncode, + const byte_t* pchSrc, + size_t nchSrc ) +{ + size_t nch = tss_encode_base64( pchSrc, nchSrc, 0, 0 ); // Like mbstowcs + + sEncode.reserve( nch ); // Make it big enough but don't resize + sEncode.resize( 0 ); // String must be clean in case of exception! + + const char* + pch = sEncode.c_str(); // Get Pointer (won't change) + + size_t nLength = // Action + tss_encode_base64( + pchSrc, nchSrc, (byte_t*)pch, nch ); + + if ( nLength == std::string::npos ) + throw std::bad_alloc(); + + sEncode.resize( nLength ); // Now it's okay to resize + + return pch; // So user can do stuff like "out << ConvertBase64()"; +} + + +std::string +cMailMessageUtil::ToBase64( const byte_t* pchSrc, size_t nchSrc ) +{ + // NOTE: It sucks to use std::string this way! Should be + // passed in by reference. + + std::string sucks; + cMailMessageUtil::ConvertBase64( sucks, pchSrc, nchSrc ); + return sucks; +} +#endif//RDIFALCO_BASE64_IMPLEMENTATION + diff --git a/src/tripwire/mailmessage.h b/src/tripwire/mailmessage.h new file mode 100644 index 0000000..d080aaa --- /dev/null +++ b/src/tripwire/mailmessage.h @@ -0,0 +1,378 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#ifndef __MAILMESSAGE_H +#define __MAILMESSAGE_H + +#ifndef __ERROR_H +#include "core/error.h" +#endif + + +#if IS_UNIX +#include +#define SOCKET int +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// +// This error class is thrown by cMailMessage and its derivatives. +// +TSS_EXCEPTION( eMailMessageError, eError ); + +// SMTP +TSS_EXCEPTION( eMailSMTPWinsockDidNotStart, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPWinsockUnloadable, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPWinsockCleanup, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPIPUnresolvable, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPSocket, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPOpenConnection, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPCloseConnection, eMailMessageError ); +TSS_EXCEPTION( eMailSMTPServer, eMailMessageError ); + +// MAPI +TSS_EXCEPTION( eMailMAPINotAvailable, eMailMessageError ); +TSS_EXCEPTION( eMailMAPIUnload, eMailMessageError ); +TSS_EXCEPTION( eMailMAPISend, eMailMessageError ); + +// piped +TSS_EXCEPTION( eMailPipedOpen, eMailMessageError ); +TSS_EXCEPTION( eMailPipedWrite, eMailMessageError ); +TSS_EXCEPTION( eMailPipedCmdFailed, eMailMessageError ); + +/////////////////////////////////////////////////////////////////////////////// +// +// This is the pure virtual base class that defines how to +// send an email message. No class derived from this one should +// have any new public methods (or data). +// +class cMailMessage +{ +public: + cMailMessage(); + virtual ~cMailMessage(); + + void AddRecipient(const TSTRING& strRecipient); + void SetFrom (const TSTRING& strFrom); + void SetFromName (const TSTRING& strFromName); + void SetSubject (const TSTRING& strSubject); + void SetBody (const TSTRING& strBody); + void AttachFile (const TSTRING& strFullPath); + + virtual bool Send() = 0; //throw(eMailMessageError) + // returns true upon success + + // This enumerates the choices of email notification methods + enum MailMethod + { + NO_METHOD, + INVALID_METHOD, + MAIL_BY_SMTP, + MAIL_BY_PIPE, + MAIL_BY_MAPI, + MAIL_NUM_ITEMS + }; + + +protected: + + + TSTRING mstrFrom; + TSTRING mstrFromName; + TSTRING mstrSubject; + TSTRING mstrBody; + std::vector mvstrRecipients; + std::vector mvstrAttachments; + + // Returns true if enough things have been set so that a useful + // email message can be sent + bool Ready(); + std::string Create822Header(); + // creates 822 header with info from the class + bool GetAttachmentsAsString( std::string& s ); +}; + +class cMailMessageUtil +{ + +public: + enum + { + _MAX_RFC822_LINE_LEN = 76, + _MAX_RFC822_HEADER_LEN = 76, + _EOL_LEN = 2 + }; + + static + const std::string::value_type* + ConvertBase64( std::string&, const byte*, size_t ); + + static bool HasNonAsciiChars( const std::string& s ); + static std::string CreateEncodedText( const std::string& text ); + + static std::string FormatAddressHeader( const std::string& name, const std::string& addr ); + static std::string FormatNonAddressHeader( const std::string& name, const std::string& val ); + + static bool ReadDate( TSTRING& strDateBuf ); + static std::string& LFToCRLF( std::string& s ); + // converts lone \n's to \r\n + +}; + +class iMimeEncoding +{ + public: + + virtual + std::string + Encode( const std::string& sIn, + int maxLineLen = -1, + int maxLen = -1 ) = 0; + // -1 means no limit + + virtual + std::string + GetEncodedWordIdentifier() = 0; + + virtual + std::string + GetContentTypeIdentifier() = 0; + + static iMimeEncoding* GetInstance(); +}; + +// TODO:BAM -- convert ToBase64 to Encode +class cBase64Encoding : public iMimeEncoding +{ + public: + virtual + std::string + Encode( const std::string& sIn, + int maxLineLen = -1, + int maxLen = -1 ) { ASSERT( false ); return ""; }; + + virtual + std::string + GetEncodedWordIdentifier() { return "B"; }; + + virtual + std::string + GetContentTypeIdentifier() { return "base64"; }; +}; + +class cQuotedPrintableEncoding : public iMimeEncoding +{ + public: + virtual + std::string + Encode( const std::string& sIn, + int maxLineLen = -1, + int maxLen = -1 ); + + virtual + std::string + GetEncodedWordIdentifier() { return "Q"; }; + + virtual + std::string + GetContentTypeIdentifier() { return "quoted-printable"; }; +}; + + + +/////////////////////////////////////////////////////////////////////////////// +// +// This class implements sending a message via SMTP +// +class cSMTPMailMessage : public cMailMessage +{ +public: + + cSMTPMailMessage(TSTRING strServerName, unsigned short portNumber); + virtual ~cSMTPMailMessage(); + + virtual bool Send(); //throw(eMailMessageError) + // returns true upon success + +private: + + // socket related member variables + SOCKET mSocket; + +#if USES_WINSOCK + // + // Types for the functions in winsock.dll + // + // These function prototypes and the pointers that use them allow us to use + // winsock without requiring the DLL to be on the end system for the application + // to run. It seems unacceptable for tripwire to fail to run at all if wsock32.dll + // is not present on the system. + // + HINSTANCE mHlibWinsock; + typedef int (PASCAL * WSASTARTUPPROC) (WORD wVersionRequired, LPWSADATA lpWSAData); + typedef SOCKET (PASCAL * SOCKETPROC) (int af, int type, int protocol); + typedef unsigned long (PASCAL * INETADDRPROC) (const char FAR * cp); + typedef int (PASCAL FAR * GETHOSTNAMEPROC) (char FAR * name, int namelen); + typedef struct hostent FAR * (PASCAL * GETHOSTBYNAMEPROC)(const char FAR * name); + typedef int (PASCAL * CONNECTPROC) (SOCKET s, const struct sockaddr FAR *name, int namelen); + typedef int (PASCAL * CLOSESOCKETPROC) (SOCKET s); + typedef int (PASCAL * SENDPROC) (SOCKET s, const char FAR * buf, int len, int flags); + typedef int (PASCAL * RECVPROC) (SOCKET s, char FAR * buf, int len, int flags); + typedef int (PASCAL * SELECTPROC) (int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout); + typedef u_long (PASCAL * LONGPROC) (u_long netlong); + typedef u_short (PASCAL * SHORTPROC) (u_short netlong); + + // pointers to the functions in wsock32.dll + + // Berkeley functions + SOCKETPROC mPfnSocket; + INETADDRPROC mPfnInetAddr; + GETHOSTNAMEPROC mPfnGethostname; + GETHOSTBYNAMEPROC mPfnGethostbyname; + CONNECTPROC mPfnConnect; + CLOSESOCKETPROC mPfnCloseSocket; + SENDPROC mPfnSend; + RECVPROC mPfnRecv; + SELECTPROC mPfnSelect; + + // winsock functions + FARPROC mPfnWSAGetLastError; + WSASTARTUPPROC mPfnWSAStartup; + FARPROC mPfnWSACleanup; + + // Endian convertion functions + LONGPROC mPfnNtohl; + LONGPROC mPfnHtonl; + SHORTPROC mPfnNtohs; + SHORTPROC mPfnHtons; + + // Methods to set the pointers to functions. + bool LoadDll(); + bool UnloadDll(); + +#endif + + void SendString( const std::string& str ); + + // methods common to windows and unix: + bool OpenConnection(); + bool CloseConnection(); + + long GetServerAddress(); + + bool MailMessage(); + bool SendAttachments(); + + bool GetAcknowledgement(); + + void DecodeError(); + + // the settings necessary for an SMTP connection: + TSTRING mstrServerName; + unsigned short mPortNumber; +}; + + +#if SUPPORTS_MAPI + + +/////////////////////////////////////////////////////////////////////////////// +// +// This class implements sending a message via MAPI under Win32 +// +class cMAPIMailMessage : public cMailMessage +{ +public: + + cMAPIMailMessage(); + virtual ~cMAPIMailMessage(); + + virtual bool Send(); //throw(eMailMessageError) + //returns true upon success + +private: + + bool InitMAPI(); + bool FinitMAPI(); + + HINSTANCE hlibMAPI; + + bool DoSendMessage(); + void PrintMAPIErrorMessage(ULONG errorMessage); +}; + +#endif + + +//#ifdef IS_UNIX + +/////////////////////////////////////////////////////////////////////////////// +// +// This class implements sending a message through a unix pipe to a program +// like 'sendmail' +// +class cPipedMailMessage : public cMailMessage +{ +public: + cPipedMailMessage(TSTRING strSendMailExePath); + virtual ~cPipedMailMessage(); + + virtual bool Send(); //throw(eMailMessageError) + // returns true upon success + +private: + + TSTRING& CreateHeader( TSTRING& strHeaderBuf ) const; + + void SendInit();// throw (eMailMessageError) + // opens a pipe to sendmail and writes the header. + + FILE* GetFilePointer() const; + // returns a pointer to the current file pointer. Only valid between + // SendInit() and SendFinit() + + void SendFinit(); //throw (eMailMessageError) + // closes the file descriptor, sending the rest of the message + + bool SendAttachments(); + // called between SendInit and SendFinit to send the attachments + + void SendString( const TSTRING& s ); + + TSTRING mstrSendMailExePath; + FILE* mpFile; // only valid with Init/Finit and Send +}; + +//#endif + +#endif // __MAILMESSAGE_H + diff --git a/src/tripwire/pipedmailmessage.cpp b/src/tripwire/pipedmailmessage.cpp new file mode 100644 index 0000000..be80c09 --- /dev/null +++ b/src/tripwire/pipedmailmessage.cpp @@ -0,0 +1,223 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtripwire.h" +#include "core/debug.h" +#include "mailmessage.h" +#include "core/fsservices.h" + +#include "tripwirestrings.h" +#include "core/msystem.h" +#include "core/stringutil.h" +#include "tw/configfile.h" + +#include "tw/twutil.h" + +// +// This file should not be compiled under anything but UNIX OS's +// + +/////////////////////////////////////////////////////////////////////////////// +// +// Constructor. Not much to do beside initialize the handle to the DLL +// +cPipedMailMessage::cPipedMailMessage(TSTRING strSendMailExePath) +{ + mstrSendMailExePath = strSendMailExePath; + mpFile = NULL; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// destructor - make sure the DLL has been unloaded +// +cPipedMailMessage::~cPipedMailMessage() +{ +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Check to make sure the message is adequately defined and send it. +// +bool cPipedMailMessage::Send() +{ + // Be sure that everything that needs to be set has been set + if (!Ready()) + { + // the message has not been adequately defined and cannot be sent. + return false; + } + + SendInit(); + + FILE* sendPipe = GetFilePointer(); + ASSERT( sendPipe != 0 ); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Get Body and Attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + bool allOK = true; + + // get body + std::string sNBody = cStringUtil::TstrToStr( mstrBody ); + + // get attachments + std::string sAttachments; + if( ! GetAttachmentsAsString( sAttachments ) ) + { + sAttachments.erase(); + allOK = false; + } + + std::string sSend = sNBody + sAttachments; + + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Make sure that there's no lone LFs + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + cMailMessageUtil::LFToCRLF( sSend ); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Determine encoding needed for body or attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + std::string sContentType = "Content-Transfer-Encoding: "; + + if( cMailMessageUtil::HasNonAsciiChars( sSend ) ) + { + // encode text + sSend = iMimeEncoding::GetInstance()->Encode( sSend, + cMailMessageUtil::_MAX_RFC822_LINE_LEN ); + + // identify content type + sContentType += iMimeEncoding::GetInstance()->GetContentTypeIdentifier(); + } + else + { + // do no encoding + + // identify content type + sContentType += "7bit"; + } + + // send content type + sContentType += "\r\n"; + SendString( cStringUtil::StrToTstr( sContentType ) ); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send Body and Attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + SendString( _T("\r\n") ); + SendString( cStringUtil::StrToTstr( sSend ) ); + + SendFinit(); + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// +// SendInit +/////////////////////////////////////////////////////////////////////////////// +void cPipedMailMessage::SendInit()// throw( eMailMessageError ) +{ + ASSERT(mpFile == 0); + + TSTRING strHeader; + strHeader += cStringUtil::StrToTstr( cMailMessage::Create822Header() ); + +#if !USES_MPOPEN + // Call _wpopen under NT + // TODO access the risk of _wpopen under NT + mpFile = _wpopen(mstrSendMailExePath.c_str(), _T("w")); +#else + // call mpopen, our safe version popen + mpFile = mpopen( (char*) mstrSendMailExePath.c_str(), _T("w") ); +#endif + if(! mpFile) + { + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_COMMAND ) + << mstrSendMailExePath; + + throw eMailPipedOpen( estr.str() ); + } + + SendString( strHeader ); +} + +void cPipedMailMessage::SendString( const TSTRING& s ) +{ + if( _ftprintf( mpFile, "%s", s.c_str() ) < 0 ) + { + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_COMMAND ) + << mstrSendMailExePath; + + throw eMailPipedOpen( estr.str() ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// SendFinit +/////////////////////////////////////////////////////////////////////////////// +void cPipedMailMessage::SendFinit() //throw ( eMailMessageError ) +{ + if(mpFile) + { +#if !USES_MPOPEN + int result = fclose( mpFile ); +#else + int result = mpclose( mpFile ); +#endif + if( result != 0 ) + { + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_COMMAND ) + << mstrSendMailExePath; + + // uh oh! something bad has happened! + throw eMailPipedCmdFailed( estr.str() ); + } + } + mpFile = 0; +} + + +FILE* cPipedMailMessage::GetFilePointer() const +{ + return mpFile; +} + diff --git a/src/tripwire/policyupdate.cpp b/src/tripwire/policyupdate.cpp new file mode 100644 index 0000000..9b86853 --- /dev/null +++ b/src/tripwire/policyupdate.cpp @@ -0,0 +1,309 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// policyupdate.cpp +#include "stdtripwire.h" +#include "policyupdate.h" +#include "tw/fcoreport.h" +#include "core/errorbucketimpl.h" +#include "integritycheck.h" +#include "updatedb.h" +#include "core/usernotify.h" +#include "fco/iterproxy.h" +#include "fco/fcopropset.h" +#include "tripwireutil.h" +#include "tripwirestrings.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" +#include "fco/genreswitcher.h" + +/////////////////////////////////////////////////////////////////////////////// +// util_FCOInSpecList -- given a spec list and an fco name, return true if the +// name belongs in one of the specs +/////////////////////////////////////////////////////////////////////////////// +static bool util_FCOInSpecList( const cFCOSpecList& specList, const cFCOName& name ) +{ + cFCOSpecListCanonicalIter iter( specList ); + for( iter.SeekBegin(); ! iter.Done(); iter.Next() ) + { + if( iter.Spec()->SpecContainsFCO( name ) ) + return true; + } + return false; +} + + +/////////////////////////////////////////////////////////////////////////////// +// util_PruneExtraObjects -- checks every object in the database against the +// provided spec set and adds them to the vector if they don't fall under any specs. +/////////////////////////////////////////////////////////////////////////////// +static void util_PruneExtraObjects( cDbDataSourceIter iter, cFCOSpecListCanonicalIter specIter, + bool bFirst = true ) +{ + if( ! bFirst ) + { + iter.Descend(); + } + + + for( iter.SeekBegin(); ! iter.Done(); /*iter.Next()*/ ) + { + // process our children first... + // + if( iter.CanDescend() ) + { + util_PruneExtraObjects( iter, specIter, false ); + } + + + if( iter.HasFCOData() ) + { + // figure out if this fco fits in the new policy + // + bool bFoundSpec = false; + for( specIter.SeekBegin(); ! specIter.Done(); specIter.Next() ) + { + if( specIter.Spec()->SpecContainsFCO( iter.GetName() ) ) + { + // this doesn't belong in the new db; remove it! + // + bFoundSpec = true; + break; + } + } + if( ! bFoundSpec ) + { + TW_NOTIFY_VERBOSE( _T("--- %s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_DB_REMOVING ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( iter.GetName() ).c_str() ); + iter.RemoveFCOData(); + } + } + // + // remove the infrastructure, if appropriate... + // this is also where the iterator incrementing occurs, so we need to + // be careful with the Next()s + // + if( ! iter.HasFCOData() ) + { + if( iter.CanDescend() && iter.CanRemoveChildArray() ) + iter.RemoveChildArray(); + if( ! iter.CanDescend() ) + iter.RemoveFCO(); + else + iter.Next(); + } + else + iter.Next(); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cPolicyUpdate::cPolicyUpdate( cGenre::Genre genreNum, const cFCOSpecList& oldPolicy, const cFCOSpecList& newPolicy, + cHierDatabase& db, cErrorBucket* pBucket ) +: mOldPolicy ( oldPolicy ), + mNewPolicy ( newPolicy ), + mDb ( db ), + mGenre ( genreNum ), + mpBucket ( pBucket ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +bool cPolicyUpdate::Execute( uint32 flags ) // throw (eError) +{ + // here is my current idea for the algorithm: first, do an integrity check with the new policy on the database and + // a special flag passed to Execute() to modify what properties are checked. Then, take the resulting + // report print to the user its contents, minus any violations that don't make sense to report (see my EPS for + // details on what doesn't get displayed) Finally, do a database update with the full report, making sure that + // properties that were from the policy are also removed from existing FCOs in the database ( I might need to + // add a parameter to DbUpdate to accomodate that). + // + + // first, do the integrity check with the new database... + // + TW_NOTIFY_NORMAL( TSS_GetString( cTripwire, tripwire::STR_PU_PROCESSING_GENRE ).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( cGenreSwitcher::GetInstance()->CurrentGenre(), true ) ); + TW_NOTIFY_NORMAL( TSS_GetString( cTripwire, tripwire::STR_PU_INTEGRITY_CHECK ).c_str() ); + // + iFCONameTranslator* pTrans = iTWFactory::GetInstance()->GetNameTranslator(); + bool bResult = true; // begin by assuming success + cFCOReport report; + cIntegrityCheck ic( mGenre, mNewPolicy, mDb, report, mpBucket ); + + // + // set up flags for the property calculator and iterators + // + uint32 icFlags = cIntegrityCheck::FLAG_COMPARE_VALID_PROPS_ONLY | + cIntegrityCheck::FLAG_INVALIDATE_EXTRA_DB_PROPS | + cIntegrityCheck::FLAG_SET_NEW_PROPS; + + if( flags & FLAG_ERASE_FOOTPRINTS_PU ) + { + icFlags |= cIntegrityCheck::FLAG_ERASE_FOOTPRINTS_IC; + } + + ic.Execute( icFlags ); + //TODO-- the second flag I just added probably makes the flag to cUpdateDb::Execute() unnecessary; + // I should probably remove it. + + + // + // Note that I will probably end up making two passes through the report (one for reporting to the user and one for + // the db update). I don't think there is a clean way to do this in a single report pass, other than rewriting + // db update, which I am not going to do. + // + cFCOReportSpecIter specIter( report, mGenre ); + for( specIter.SeekBegin(); ! specIter.Done(); specIter.Next() ) + { + // notify the user of what we are doing... + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_PROCESSING ).c_str(), + pTrans->ToStringDisplay( specIter.GetSpec()->GetStartPoint() ).c_str() ); + + // + // report objects in the added set should only be reported if they fall in a spec + // in the old policy + // + iFCOSet* pAddSet = specIter.GetAddedSet(); + const cIterProxy pIter = pAddSet->GetIter(); + for( pIter->SeekBegin(); ! pIter->Done(); pIter->Next() ) + { + if( util_FCOInSpecList( mOldPolicy, pIter->FCO()->GetName() ) ) + { + // this is an error that should be reported to the user. + ePolicyUpdateAddedFCO e( pTrans->ToStringDisplay( pIter->FCO()->GetName() ) ); + if( (flags & ANAL) == 0 ) + e.SetFlags( eError::NON_FATAL ); + else + e.SetFlags( eError::SUPRESS_THIRD_MSG ); + mpBucket->AddError( e ); + bResult = false; + } + } + // + // objects in the removed set should only be reported if they fall in a spec in the + // new policy.. + // + iFCOSet* pRmSet = specIter.GetRemovedSet(); + const cIterProxy pRmIter = pRmSet->GetIter(); + for( pRmIter->SeekBegin(); ! pRmIter->Done(); pRmIter->Next() ) + { + if( util_FCOInSpecList( mNewPolicy, pRmIter->FCO()->GetName() ) ) + { + // this is an error that should be reported to the user. + ePolicyUpdateRemovedFCO e( pTrans->ToStringDisplay( pRmIter->FCO()->GetName() ) ); + + if( (flags & ANAL) == 0 ) + e.SetFlags( eError::NON_FATAL ); + else + e.SetFlags( eError::SUPRESS_THIRD_MSG ); + mpBucket->AddError( e ); + bResult = false; + } + } + // + // every object in the changed set should be document.... + // + cFCOReportChangeIter changeIter( specIter ); + for( changeIter.SeekBegin(); ! changeIter.Done(); changeIter.Next() ) + { + //---------------------------------------------------------------- + // I need to construct a string that contains all of the + // property names that have changed. + //---------------------------------------------------------------- + TSTRING badPropStr = TSS_GetString( cTripwire, tripwire::STR_PU_BAD_PROPS ); + + badPropStr += pTrans->ToStringDisplay( changeIter.GetOld()->GetName() ); + const cFCOPropVector& changeVector = changeIter.GetChangeVector(); + for(int i=0; i < changeVector.GetSize(); i++) + { + if(changeVector.ContainsItem(i)) + { + badPropStr += _T("\n> "); + badPropStr += changeIter.GetOld()->GetPropSet()->GetPropName(i); + } + } + + // add this to the error bucket + ePolicyUpdateChangedFCO e( badPropStr ); + if( (flags & ANAL) == 0 ) + e.SetFlags( eError::NON_FATAL ); + else + e.SetFlags( eError::SUPRESS_THIRD_MSG ); + mpBucket->AddError( e ); + bResult = false; + } + } + // + // now, we will update the database with everything in the report... + // TODO -- don't do this if the anal flag was passed in + // + TW_NOTIFY_NORMAL( TSS_GetString( cTripwire, tripwire::STR_PU_UPDATE_DB ).c_str() ); + // + cUpdateDb update( mDb, report, mpBucket ); + + uint32 updateDBFlags = cUpdateDb::FLAG_REPLACE_PROPS; + if( flags & FLAG_ERASE_FOOTPRINTS_PU ) + updateDBFlags |= cUpdateDb::FLAG_ERASE_FOOTPRINTS_UD; + + update.Execute( updateDBFlags ); + + + // the last thing that we have to do is to remove everything that is still + // in the database that does not belong in the new database (ie -- does not fall under any + // new rules) + // + // TODO -- is there any way to do this that does not involve iterating over the entire database? + // TODO -- I should probably write a general-purpose database iterator class to do this... + // + + TW_NOTIFY_NORMAL( TSS_GetString( cTripwire, tripwire::STR_PU_PRUNING ).c_str() ); + // + cDbDataSourceIter i( &mDb ); + i.SetErrorBucket(mpBucket); + + if( flags & FLAG_ERASE_FOOTPRINTS_PU ) + i.SetIterFlags( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + + const cFCOSpecListCanonicalIter newPolIter( mNewPolicy ); + util_PruneExtraObjects( i, newPolIter ); + + return bResult; +} + diff --git a/src/tripwire/policyupdate.h b/src/tripwire/policyupdate.h new file mode 100644 index 0000000..079b371 --- /dev/null +++ b/src/tripwire/policyupdate.h @@ -0,0 +1,87 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// policyupdate.h +// +#ifndef __POLICYUPDATE_H +#define __POLICYUPDATE_H + +#ifndef __FCOSPECLIST_H +#include "fco/fcospeclist.h" +#endif +#ifndef __HIERDATABASE_H +#include "db/hierdatabase.h" +#endif +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +class cErrorBucket; + + +//////////////////////////////////////////////////////////// +// Policy Update Exceptions +//////////////////////////////////////////////////////////// +TSS_EXCEPTION( ePolicyUpdate, eError ); +TSS_EXCEPTION( ePolicyUpdateAddedFCO, ePolicyUpdate ); +TSS_EXCEPTION( ePolicyUpdateRemovedFCO, ePolicyUpdate ); +TSS_EXCEPTION( ePolicyUpdateChangedFCO, ePolicyUpdate ); + +class cPolicyUpdate +{ +public: + cPolicyUpdate( cGenre::Genre genreNum, const cFCOSpecList& oldPolicy, const cFCOSpecList& newPolicy, + cHierDatabase& db, cErrorBucket* pBucket ); + + bool Execute( uint32 flags = 0 ) ; // throw (eError) + // if false is returned, then there was at least one conflict that came up during the policy + // update, and if tripwire was run in anal mode then the policy update should fail. + + enum Flags + { + ANAL = 0x00000001, // if this is set, then we are in anal mode. This affects whether error + // messages appear as "Error" or "Warning" + FLAG_ERASE_FOOTPRINTS_PU= 0x00000002 + // when this flag is set, cPolicyUpdate will attempt undo any inadvertant modifications + // it may make when executing. + }; + +private: + const cFCOSpecList& mOldPolicy; + const cFCOSpecList& mNewPolicy; + cHierDatabase& mDb; + cGenre::Genre mGenre; + cErrorBucket* mpBucket; +}; + +#endif //__POLICYUPDATE_H + diff --git a/src/tripwire/resource.h b/src/tripwire/resource.h new file mode 100644 index 0000000..fbe9e46 --- /dev/null +++ b/src/tripwire/resource.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + diff --git a/src/tripwire/smtpmailmessage.cpp b/src/tripwire/smtpmailmessage.cpp new file mode 100644 index 0000000..84ec72c --- /dev/null +++ b/src/tripwire/smtpmailmessage.cpp @@ -0,0 +1,652 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtripwire.h" +#include "core/debug.h" +#include "mailmessage.h" +#include "tw/configfile.h" +#include "tw/twutil.h" +#include "tripwirestrings.h" +#include "core/stringutil.h" +#include +#include "core/msystem.h" +#include "core/file.h" + +#if IS_UNIX + +#include + +//All the spleck that it takes to run sockets in Unix... +#include +#include +#include +#include +#include +#include +#include +#include + +/* Some systems like Solaris and AIX don't define + * INADDR_NONE, but it's pretty standard. If not, + * then the OS _should_ define it for us. + */ +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#include + +#define INVALID_SOCKET -1 + +#ifndef HAVE_GETHOSTNAME +static int gethostname( char* name, int namelen ) +{ + name[0] = '\0'; + + struct utsname myname; + uname( & myname ); + + if ( strlen( myname.nodename ) < (unsigned int)namelen ) + { + strcpy( name, myname.nodename ); + return 0; + } + else + { + //Not enough room in the buffer for the nodename + return -1; + // equivalent of SOCKET_ERROR + } +} +#endif + + // Unix does not require us to go though any silly DLL hoops, so we'll + // just #define the pointers to functions needed by Windows to be the + // berkely functions. + #define mPfnSocket socket + #define mPfnInetAddr inet_addr + #define mPfnGethostname gethostname + #define mPfnGethostbyname gethostbyname + #define mPfnConnect connect + #define mPfnCloseSocket close + #define mPfnSend send + #define mPfnRecv recv + #define mPfnSelect select + #define mPfnNtohl ntohl + #define mPfnHtonl htonl + #define mPfnNtohs ntohs + #define mPfnHtons htons +#endif + +// +// TODO - maybe convert this SMTP code to non-blocking socket calls, or use +// another thread, or make it fail gracefully when the server fails to +// respond at all. +// + +/////////////////////////////////////////////////////////////////////////////// +// +// Construct the SMTP Mail Message Sender +// +cSMTPMailMessage::cSMTPMailMessage(TSTRING strServerName, unsigned short portNumber) +{ + mstrServerName = strServerName; + mPortNumber = portNumber; + mSocket = INVALID_SOCKET; + +#if USES_WINSOCK + mHlibWinsock = NULL; + + mPfnSocket = NULL; + mPfnInetAddr = NULL; + mPfnGethostname = NULL; + mPfnGethostbyname = NULL; + mPfnConnect = NULL; + mPfnCloseSocket = NULL; + mPfnSend = NULL; + mPfnRecv = NULL; + mPfnSelect = NULL; + + mPfnWSAStartup = NULL; + mPfnWSACleanup = NULL; + mPfnWSAGetLastError = NULL; + + mPfnNtohl = NULL; + mPfnHtonl = NULL; + mPfnNtohs = NULL; + mPfnHtons = NULL; +#endif // USES_WINSOCK +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Clean up any thing left over from sending or failing to send the message. +// +cSMTPMailMessage::~cSMTPMailMessage() +{ +} + + + + +/////////////////////////////////////////////////////////////////////////////// +// +// Get the IP address from the the server string. It's OK to have +// this function look up a string like "192.34.64.23" or one like +// "mail.stinkycheese.com" +// +long cSMTPMailMessage::GetServerAddress() +{ + bool bIsNumeric = true; + + // Decide if the string is in the form "127.0.0.1" or "mail.domain.com" + // by looking for an character that is not a digit or a period. + for (std::vector::size_type i=0; i < mstrServerName.length(); i++) + { + if (mstrServerName[i] != '.' && (mstrServerName[i]<'0' || mstrServerName[i]>'9')) + { + bIsNumeric = false; + } + } + + std::string sNarrowString = cStringUtil::TstrToStr(mstrServerName); + + if (bIsNumeric) + { + // convert the numberic address to a long + return mPfnInetAddr(sNarrowString.c_str()); + } + else + { + // do a DNS lookup of the hostname and get the long + hostent *ent = mPfnGethostbyname(sNarrowString.c_str()); + if (!ent) + return INADDR_NONE; + else + return *(long *)ent->h_addr_list[0]; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Create and open the socket connection +// +bool cSMTPMailMessage::OpenConnection() +{ + // Initialize the socket structure + sockaddr_in sockAddrIn; + memset(&sockAddrIn, 0, sizeof(sockaddr)); + sockAddrIn.sin_family = AF_INET; + sockAddrIn.sin_port = mPfnHtons(mPortNumber); + uint32 iServerAddress = GetServerAddress(); + +#if IS_UNIX + sockAddrIn.sin_addr.s_addr = iServerAddress; +#endif + if ( iServerAddress == INADDR_NONE ) + { + DecodeError(); + + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_SERVER ) + << mstrServerName; + + throw eMailSMTPIPUnresolvable(estr.str()); + return false; + } + + // Create the socket + mSocket = mPfnSocket(AF_INET, SOCK_STREAM, 0); + if (mSocket == INVALID_SOCKET) + { + DecodeError(); + throw eMailSMTPSocket(); + return false; + } + + // Make the connection + int connectVal = mPfnConnect(mSocket, (struct sockaddr *)&sockAddrIn, sizeof(sockAddrIn)); + if (connectVal < 0) + { + DecodeError(); + + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_SERVER ) + << mstrServerName; + + throw eMailSMTPOpenConnection(estr.str()); + return false; + } + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Close the socket connection +// +bool cSMTPMailMessage::CloseConnection() +{ + if ( INVALID_SOCKET != mSocket ) + { + // close the connection + int closeVal = mPfnCloseSocket(mSocket); + if (closeVal != 0) + { + DecodeError(); + throw eMailSMTPCloseConnection(); + return false; + } + return true; + } + else + { + return true; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Call this function to send the mail message once the requisite +// methods have been called to define the mail message. +// +bool cSMTPMailMessage::Send() +{ + // Be sure that everything that needs to be set has been set + if (!Ready()) + { + // the message has not been adequately defined and cannot be sent. + return false; + } + + + bool errorOccured = false; + + if ((errorOccured = !OpenConnection()) == false) + { + errorOccured |= !MailMessage(); + errorOccured |= !CloseConnection(); + } + + + return !errorOccured; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Once the connection is set, this function conducts the SMTP protocol +// to actually send the message. +// +bool cSMTPMailMessage::MailMessage() +{ + cDebug d("cSMTPMailMessage::MailMessage()"); + std::string sNarrowString; + + // Get the greeting message from the SMTP server + if (!GetAcknowledgement()) + return false; + + char sLocalHost[256]; // It's alright for this to be a fixed buffer, since + // we will be explicitely passing it's length to + // mpfnGethostname (see below). It won't be used + // after that. + + std::ostringstream strmSend; + // This should be a stream object, so we don't have + // to use nasty calls to sprintf that might overflow + // the buffer. Before, we used a fixed buffer of 512 + // characters, and there's really no guarantee that any + // of the string objects (that we are printing to the buffer + // from) will be below this limit. + + ASSERT( strmSend.str().length() == 0 ); // This bad boy better be empty. + + // get our hostname for the HELO message + if (mPfnGethostname(sLocalHost, 256) < 0 ) { + DecodeError(); + return false; + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Set up connection + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + // Say hello + strmSend.str(""); //Clear the stream buffer. + strmSend << "HELO " << sLocalHost << "\r\n"; //Fill the stream buffer. + SendString( strmSend.str() ); + if (!GetAcknowledgement()) + return false; + + + strmSend.str(""); //Clear the stream buffer. + strmSend << "MAIL FROM:<" + << cStringUtil::TstrToStr(mstrFrom) + << ">\r\n"; + SendString( strmSend.str() ); + if (!GetAcknowledgement()) + return false; + + // Say who all we're sending to + strmSend.str(""); //Clear the stream buffer. + for (std::vector::size_type i=0; i\r\n"; + + SendString( strmSend.str() ); + + if (!GetAcknowledgement()) + return false; + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Start data + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + // Send start the message process + SendString( "DATA\r\n" ); + if (!GetAcknowledgement()) + return false; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send Header + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + // set up header + strmSend.str(""); + strmSend << cMailMessage::Create822Header(); + SendString( strmSend.str() ); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Get Body and Attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + bool allOK = true; + + + // get body + std::string sNBody = cStringUtil::TstrToStr( mstrBody ); + + std::string sAttachments; + if( ! GetAttachmentsAsString( sAttachments ) ) + { + sAttachments.erase(); + allOK = false; + } + + std::string sSend = sNBody + sAttachments; + + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Make sure that there's no lone LFs + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + cMailMessageUtil::LFToCRLF( sSend ); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Determine encoding needed for body or attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + std::string sContentType = "Content-Transfer-Encoding: "; + + if( cMailMessageUtil::HasNonAsciiChars( sSend ) ) + { + // encode text + sSend = iMimeEncoding::GetInstance()->Encode( sSend, + cMailMessageUtil::_MAX_RFC822_LINE_LEN ); + + // identify content type + sContentType += iMimeEncoding::GetInstance()->GetContentTypeIdentifier(); + } + else + { + // do no encoding + + // identify content type + sContentType += "7bit"; + } + + // send content type + sContentType += "\r\n"; + SendString( sContentType ); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send Body and Attachments + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + SendString( "\r\n" ); + SendString( sSend ); + + // send the end of message line + SendString( "\r\n.\r\n" ); + if (!GetAcknowledgement()) + return false; + + // send the quit message + SendString( "QUIT" ); + + return allOK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Get the response code from the server to see if the last command +// we sent was accepted. +// +bool cSMTPMailMessage::GetAcknowledgement() +{ + cDebug d( "cSMTPMailMessage::GetAcknowledgement" ); + + const int bufsize = 512; + TCHAR sRecvString[bufsize+1]; // This string is and should be unicode + char sTempString[bufsize+1]; // This string is not, and should not be unicode + int bytes; + int i=0; + + // make socket array for the call to select + fd_set socketSet; + // need comment + timeval tv; + + +#if IS_UNIX + FD_ZERO( &socketSet ); + FD_SET( mSocket, &socketSet ); +#else + socketSet.fd_count = 1; + socketSet.fd_array[0] = mSocket; +#endif + + // set the timeout time to sixty seconds + tv.tv_sec = 60; + tv.tv_usec = 0; + + // Wait up to sixty seconds fot data to show up on the socket to be read + if (mPfnSelect(mSocket+1, &socketSet, NULL, NULL, &tv) == 1) + { + // Get the reply message + bytes = mPfnRecv(mSocket, sTempString, 512, 0); + + // TODO:BAM -- this should be changed to use 'cStringUtil' + for (int j=0; j= 200 && code < 400) + { + // Error codes in the range of 200-399 indicate success. See RFC 821 + return true; + } + else + { + // Error codes other than 200-399 indicate an error or a failure. See RFC 821 + TOSTRINGSTREAM estr; + estr << TSS_GetString( cTripwire, tripwire::STR_ERR2_MAIL_MESSAGE_SERVER_RETURNED_ERROR ) + << sRecvString; + + throw eMailSMTPServer(estr.str()); + return false; + } +} + +void cSMTPMailMessage::SendString( const std::string& str ) +{ + cDebug d("util_SendString()"); + + if( str.length() < 800 ) + d.TraceDebug( "Sending \"%s\"\n", str.c_str() ); + else + d.TraceDebug( "Sending (truncated in this debug output)\"%s\"\n", std::string( str.c_str(), 800 ).c_str() ); + mPfnSend( mSocket, str.c_str(), str.length(), 0 ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// +// Get debug info when a error is encountered. +// +void cSMTPMailMessage::DecodeError() +{ +#if defined(_DEBUG) + +#if USES_WINSOCK + // + // decode an error condition encountered by Windows sockets. + // TODO - write something less technical to explain what when wrong. Windows + // message names are not good error strings for a shipping product. + // + int error = mPfnWSAGetLastError(); + fprintf(stderr, "Encountered winsock error message %d", error); + struct ErrorStruct + { + const char *msg; + int error; + } + static const errors[52] = + { + { "WSAEINTR", (WSABASEERR+4) }, + { "WSAEBADF", (WSABASEERR+9) }, + { "WSAEACCES", (WSABASEERR+13) }, + { "WSAEFAULT", (WSABASEERR+14) }, + { "WSAEINVAL", (WSABASEERR+22) }, + { "WSAEMFILE", (WSABASEERR+24) }, + { "WSAEWOULDBLOCK", (WSABASEERR+35) }, + { "WSAEINPROGRESS", (WSABASEERR+36) }, + { "WSAEALREADY", (WSABASEERR+37) }, + { "WSAENOTSOCK", (WSABASEERR+38) }, + { "WSAEDESTADDRREQ", (WSABASEERR+39) }, + { "WSAEMSGSIZE", (WSABASEERR+40) }, + { "WSAEPROTOTYPE", (WSABASEERR+41) }, + { "WSAENOPROTOOPT", (WSABASEERR+42) }, + { "WSAEPROTONOSUPPORT", (WSABASEERR+43) }, + { "WSAESOCKTNOSUPPORT", (WSABASEERR+44) }, + { "WSAEOPNOTSUPP", (WSABASEERR+45) }, + { "WSAEPFNOSUPPORT", (WSABASEERR+46) }, + { "WSAEAFNOSUPPORT", (WSABASEERR+47) }, + { "WSAEADDRINUSE", (WSABASEERR+48) }, + { "WSAEADDRNOTAVAIL", (WSABASEERR+49) }, + { "WSAENETDOWN", (WSABASEERR+50) }, + { "WSAENETUNREACH", (WSABASEERR+51) }, + { "WSAENETRESET", (WSABASEERR+52) }, + { "WSAECONNABORTED", (WSABASEERR+53) }, + { "WSAECONNRESET", (WSABASEERR+54) }, + { "WSAENOBUFS", (WSABASEERR+55) }, + { "WSAEISCONN", (WSABASEERR+56) }, + { "WSAENOTCONN", (WSABASEERR+57) }, + { "WSAESHUTDOWN", (WSABASEERR+58) }, + { "WSAETOOMANYREFS", (WSABASEERR+59) }, + { "WSAETIMEDOUT", (WSABASEERR+60) }, + { "WSAECONNREFUSED", (WSABASEERR+61) }, + { "WSAELOOP", (WSABASEERR+62) }, + { "WSAENAMETOOLONG", (WSABASEERR+63) }, + { "WSAEHOSTDOWN", (WSABASEERR+64) }, + { "WSAEHOSTUNREACH", (WSABASEERR+65) }, + { "WSAENOTEMPTY", (WSABASEERR+66) }, + { "WSAEPROCLIM", (WSABASEERR+67) }, + { "WSAEUSERS", (WSABASEERR+68) }, + { "WSAEDQUOT", (WSABASEERR+69) }, + { "WSAESTALE", (WSABASEERR+70) }, + { "WSAEREMOTE", (WSABASEERR+71) }, + { "WSAEDISCON", (WSABASEERR+101) }, + { "WSASYSNOTREADY", (WSABASEERR+91) }, + { "WSAVERNOTSUPPORTED", (WSABASEERR+92) }, + { "WSANOTINITIALISED", (WSABASEERR+93) }, + { "WSAHOST_NOT_FOUND", (WSABASEERR+1001) }, + { "WSATRY_AGAIN", (WSABASEERR+1002) }, + { "WSANO_RECOVERY", (WSABASEERR+1003) }, + { "WSANO_DATA", (WSABASEERR+1004) }, + { NULL, 0 } + }; + + int i = 0; + while (errors[i].msg) + { + if (errors[i].error == error) + { + fprintf(stderr, ": %s", errors[i].msg); + break; + } + i++; + } + fprintf(stderr, "\n"); +#endif // USES_WINSOCK + +#if IS_UNIX + + // + // TODO - Write what ever error reporting will be needed under unix. + // + +#endif // IS_UNIX + +#endif // defined(_DEBUG) +} + diff --git a/src/tripwire/stdtripwire.cpp b/src/tripwire/stdtripwire.cpp new file mode 100644 index 0000000..76e5c8c --- /dev/null +++ b/src/tripwire/stdtripwire.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtripwire.cpp +// Date....: 5/12/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtripwire.h" + +// eof: stdtripwire.cpp diff --git a/src/tripwire/stdtripwire.h b/src/tripwire/stdtripwire.h new file mode 100644 index 0000000..e62786d --- /dev/null +++ b/src/tripwire/stdtripwire.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtripwire.h +// +// Standard includes for the tripwire library. +// + +#include "core/stdcore.h" + diff --git a/src/tripwire/syslog_trip.cpp b/src/tripwire/syslog_trip.cpp new file mode 100644 index 0000000..ed0b49f --- /dev/null +++ b/src/tripwire/syslog_trip.cpp @@ -0,0 +1,248 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// syslog.cpp +// + +#include "stdtripwire.h" +#include "syslog_trip.h" + +#if HAVE_SYSLOG_H +#include +#endif + +#if HAVE_SYS_SYSLOG_H +#include +#endif + +#if SUPPORTS_EVENTLOG +#include "tripwiremsg.h" +#include "tw/systeminfo.h" +#endif + +// next three includes are for error reporting +#include "tw/twutil.h" +#include "tw/twerrors.h" +#include "tw/twstrings.h" + +/////////////////////////////////////////////////////////////////////////////// +// Syslog +/////////////////////////////////////////////////////////////////////////////// + +#if SUPPORTS_EVENTLOG +static void InitEventLog(); +#endif + +void cSyslog::Log(const TCHAR* programName, cSyslog::LogType logType, const TCHAR* message) +{ +#if HAVE_SYSLOG_H + + (void)logType; // logType is not used for Unix syslog + +#ifdef _UNICODE + std::basic_string identString; + std::basic_string msgString; + int count; + + count = sizeof(char) * MB_CUR_MAX * _tcslen(programName); // note we use sizeof(char) * 2 because mb chars can be two bytes long + identString.resize(count); + count = wcstombs((char*)identString.data(), programName, count); + identString.resize(count); // count will be set to number of bytes written + + count = sizeof(char) * MB_CUR_MAX * _tcslen(message); + msgString.resize(count); + count = wcstombs((char*)msgString.data(), message, count); + msgString.resize(count); + + const char* ident = programName.data(); + const char* msg = message.data(); +#else + ASSERT(sizeof(TCHAR) == sizeof(char)); + const char* ident = programName; + const char* msg = message; +#endif + + openlog(ident, LOG_PID, LOG_USER); + syslog(LOG_NOTICE, "%s", msg); + closelog(); + +#elif SUPPORTS_EVENTLOG + + static bool eventLogInitialized = false; + if (!eventLogInitialized) + { + InitEventLog(); + eventLogInitialized = true; + } + + HANDLE h = RegisterEventSource(NULL, _T("Tripwire")); + if (h != NULL) + { + LPCTSTR stringArray[1]; + stringArray[0] = message; + + WORD type; + DWORD id; + + switch (logType) + { + default: + ASSERT(false); + case LOG_SUCCESS: + type = EVENTLOG_INFORMATION_TYPE; + id = MSG_TRIPWIRE_GENERIC_SUCCESS; + break; + case LOG_INFORMATION: + type = EVENTLOG_INFORMATION_TYPE; + id = MSG_TRIPWIRE_GENERIC_INFO; + break; + case LOG_WARNING: + type = EVENTLOG_WARNING_TYPE; + id = MSG_TRIPWIRE_GENERIC_WARNING; + break; + case LOG_ERROR: + type = EVENTLOG_ERROR_TYPE; + id = MSG_TRIPWIRE_GENERIC_ERROR; + break; + } + + BOOL ret = ReportEvent( + h, + type, // event type + 0, // catagory + id, // event id + 0, // user sid + 1, // num strings + 0, // raw binary data size + stringArray, // array of strings + 0 // raw binrary data + ); + + if (!ret) + { + eTWSyslog e( TSS_GetString(cTW, tw::STR_REPORTEVENT_FAILED).c_str(), eError::NON_FATAL ); + cTWUtil::PrintErrorMsg(e); + } + + DeregisterEventSource(h); + } + +#else + // No support for syslog like functionality + //ASSERT(false); +#endif +} + + +#if SUPPORTS_EVENTLOG +static void InitEventLog() +{ + // To initialize the event log, we need to verify that Tripwire + // is a valid event source. + // To do this we look up the value for the Tripwire event source. If it + // exists, the the dest is a file called "tripwire.exe" (or this executable) and the + // file exists, then we assume that the event source is set correctly. + + HKEY hKey; + DWORD disposition; + + if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\Tripwire"), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &disposition) == ERROR_SUCCESS && + disposition == REG_OPENED_EXISTING_KEY) + { + DWORD type, count; + + // We need to insure we have back slashes in our exepath + TSTRING exepath = cSystemInfo::GetExePath(); + TSTRING::iterator i; + for (i = exepath.begin(); i != exepath.end(); ++i) + if (*i == _T('/')) + *i = _T('\\'); + + if (RegQueryValueEx(hKey, _T("TypesSupported"), 0, &type, 0, &count) == ERROR_SUCCESS && + type == REG_DWORD && + RegQueryValueEx(hKey, _T("EventMessageFile"), 0, &type, 0, &count) == ERROR_SUCCESS && + type == REG_EXPAND_SZ) + { + TSTRING data; + data.resize(count); + if (RegQueryValueEx(hKey, _T("EventMessageFile"), 0, &type, (LPBYTE)data.data(), &count) == ERROR_SUCCESS && + type == REG_EXPAND_SZ) + { + TSTRING::size_type lastDelimitor; + lastDelimitor = data.find_last_of(_T('\\')); + if (lastDelimitor == TSTRING::npos) + lastDelimitor = (TSTRING::size_type)-1; + + if (_tcscmp(exepath.c_str(), data.c_str()) == 0) + { + RegCloseKey(hKey); + return; + } + + if (_tcsicmp(_T("tripwire.exe"), data.substr(lastDelimitor + 1).c_str()) == 0) + { + HINSTANCE hInst = LoadLibraryEx(data.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE); + if (hInst != NULL) + { + FreeLibrary(hInst); + RegCloseKey(hKey); + return; + } + } + } + } + + // If we got here then the event source is not set up correctly + + // Add the name to the EventMessageFile subkey. + RegSetValueEx(hKey, // subkey handle + _T("EventMessageFile"), // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE) exepath.c_str(), // pointer to value data + sizeof(TCHAR)*(exepath.length() + 1)); // length of value data + + // Set the supported event types in the TypesSupported subkey. + DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + + RegSetValueEx(hKey, // subkey handle + _T("TypesSupported"), // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwData, // pointer to value data + sizeof(DWORD)); // length of value data + + RegCloseKey(hKey); + } +} +#endif + diff --git a/src/tripwire/syslog_trip.h b/src/tripwire/syslog_trip.h new file mode 100644 index 0000000..9c8de99 --- /dev/null +++ b/src/tripwire/syslog_trip.h @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// syslog.h +// +// cSyslog class. Abstracts logging to Unix syslog or NT Event Log +// + +#ifndef __SYSLOG_H +#define __SYSLOG_H + +class cSyslog +{ +public: + enum LogType + { + LOG_SUCCESS, + LOG_INFORMATION, + LOG_WARNING, + LOG_ERROR + }; + + static void Log(const TCHAR* programName, cSyslog::LogType logType, const TCHAR* message); + // logs message the syslog mechanism on Unix. + // currently a NOOP on Windows (but asserts in debug mode) + // TODO: Should this be a fsservices function? +}; + + +#endif + diff --git a/src/tripwire/tripwire.cpp b/src/tripwire/tripwire.cpp new file mode 100644 index 0000000..4b97b47 --- /dev/null +++ b/src/tripwire/tripwire.cpp @@ -0,0 +1,73 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: tripwire.cpp +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtripwire.h" +#include "tripwire.h" +#include "tripwireerrors.h" + +#include "core/core.h" +#include "db/db.h" +#include "twcrypto/twcrypto.h" +#include "twparser/twparser.h" +#include "tw/tw.h" +#include "fco/fco.h" + + +#include "fs/fs.h" +#include "util/util.h" + +/////////////////////////////////////////////////////////////////////////////// +// cTripwire +/////////////////////////////////////////////////////////////////////////////// +TSS_ImplementPackage( cTripwire ) + +cTripwire::cTripwire() +{ + TSS_Dependency( cCore ); + TSS_Dependency( cDb ); + TSS_Dependency( cTWCrypto ); + TSS_Dependency( cTWParser ); + TSS_Dependency( cTW ); + TSS_Dependency( cFCO ); + TSS_Dependency( cFS ); + TSS_Dependency( cUtil ); + + TSS_REGISTER_PKG_ERRORS( tripwire ) +} + +// eof: tripwire.cpp + diff --git a/src/tripwire/tripwire.h b/src/tripwire/tripwire.h new file mode 100644 index 0000000..b725e76 --- /dev/null +++ b/src/tripwire/tripwire.h @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: tripwire.h +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// Package initialization class +// + +#ifndef __TRIPWIRE_H +#define __TRIPWIRE_H + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include "core/package.h" + + +TSS_BeginPackage( cTripwire ) + + TSS_DECLARE_STRINGTABLE; + +public: + cTripwire(); + +TSS_EndPackage( cTripwire ) + + +#endif + diff --git a/src/tripwire/tripwireerrors.cpp b/src/tripwire/tripwireerrors.cpp new file mode 100644 index 0000000..6277541 --- /dev/null +++ b/src/tripwire/tripwireerrors.cpp @@ -0,0 +1,113 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////// +// tripwireerrors.cpp +// +// Registers all error strings in the tripwire package +// + +#include "stdtripwire.h" +#include "tripwireerrors.h" + +#include "mailmessage.h" +#include "policyupdate.h" +#include "updatedb.h" +#include "integritycheck.h" +#include "twcmdline.h" +#include "twcmdlineutil.h" + +TSS_BEGIN_ERROR_REGISTRATION( tripwire ) + +// MailMessage +TSS_REGISTER_ERROR( eMailMessageError(), _T("Mail message error.") ); + +// SMTP +TSS_REGISTER_ERROR( eMailSMTPWinsockDidNotStart(), _T("An internet connection could not be found.") ); +TSS_REGISTER_ERROR( eMailSMTPWinsockUnloadable(), _T("WSOCK32.DLL could not be loaded.") ); +TSS_REGISTER_ERROR( eMailSMTPWinsockCleanup(), _T("The internet connection could not be terminated properly.") ); +TSS_REGISTER_ERROR( eMailSMTPIPUnresolvable(), _T("The IP address could not be resolved: ") ); +TSS_REGISTER_ERROR( eMailSMTPSocket(), _T("Socket for an SMTP connection could not be created.") ); +TSS_REGISTER_ERROR( eMailSMTPOpenConnection(), _T("The SMTP connection could not be established.") ); +TSS_REGISTER_ERROR( eMailSMTPCloseConnection(), _T("The SMTP connection could not be properly closed.") ); +TSS_REGISTER_ERROR( eMailSMTPServer(), _T("The SMTP server returned an error.") ); + +// MAPI +TSS_REGISTER_ERROR( eMailMAPINotAvailable(), _T("MAPI is not available.") ); +TSS_REGISTER_ERROR( eMailMAPIUnload(), _T("MAPI32.DLL could not be loaded.") ); +TSS_REGISTER_ERROR( eMailMAPISend(), _T("Sending message via MAPI failed.") ); + +// Piped +TSS_REGISTER_ERROR( eMailPipedOpen(), _T("Problem opening mail pipe.") ); +TSS_REGISTER_ERROR( eMailPipedWrite(), _T("Problem writing to mail pipe.") ); +TSS_REGISTER_ERROR( eMailPipedCmdFailed(), _T("Execution of mail program failed.") ); + +// Policy Update +TSS_REGISTER_ERROR( ePolicyUpdate(), _T("Policy Update") ); +TSS_REGISTER_ERROR( ePolicyUpdateAddedFCO(), _T("Policy Update Added Object.\nAn object has been added since the database was last updated.\nObject name: ") ); +TSS_REGISTER_ERROR( ePolicyUpdateRemovedFCO(), _T("Policy Update Removed Object.\nAn object has been removed since the database was last updated.\nObject name: ") ); +TSS_REGISTER_ERROR( ePolicyUpdateChangedFCO(), _T("Policy Update Changed Object.\nAn object has been changed since the database was last updated.\nObject name: ") ); + +// Update Db +TSS_REGISTER_ERROR( eUpdateDb(), _T("Database Update") ); +TSS_REGISTER_ERROR( eUpdateDbAddedFCO(), _T("Database Update Addition.\nThe report may be out of sync with current database.\nThe report indicates an object has been added but the object is already in the database.\nObject name: ") ); +TSS_REGISTER_ERROR( eUpdateDbRemovedFCO(), _T("Database Update Object Not Found.\nThe report may be out of sync with current database.\nThe report indicates that an object has been removed but the object is not in the database.\nObject name: ") ); +TSS_REGISTER_ERROR( eUpdateDbChangedFCO(), _T("Database Update Old Property Mismatch.\nThe report may be out of sync with current database.\nThe old properties for an object do not match the properites stored in the database.\nObject name: ") ); + +// IC +TSS_REGISTER_ERROR( eIC(), _T("Integrity Check") ); +TSS_REGISTER_ERROR( eICFCONotInSpec(), _T("Integrity Check Internal Error.\nObject to be checked is not in any database rules.\n") ); +TSS_REGISTER_ERROR( eICFCONotInDb(), _T("Integrity Check Internal Error.\nObject to be checked is not in database.\n") ); +TSS_REGISTER_ERROR( eICFCOCreate(), _T("Integrity Check Internal Error.\nObject to be checked could not be created in the database.\n") ); +TSS_REGISTER_ERROR( eICBadPol(), _T("Policy file does not match policy used to create database.") ); +TSS_REGISTER_ERROR( eICUnknownGenre(), _T("Invalid section specified on the command line.") ); +TSS_REGISTER_ERROR( eICBadSevVal(), _T("Invalid severity level specified on the command line.") ); +TSS_REGISTER_ERROR( eICInappropriateGenre(), _T("Inappropriate section specified on the command line.") ); +TSS_REGISTER_ERROR( eICDifferentUsers(), _T("Current user differs from one who created database.") ); +TSS_REGISTER_ERROR( eICMismatchingParams(), _T("Mismatch in specified command line parameters: ") ); +TSS_REGISTER_ERROR( eTWInvalidConfigFileKey(), _T("Configuration file contains an invalid variable.") ); +TSS_REGISTER_ERROR( eTWPassForUnencryptedDb(), _T("Passphrase specified for an unencrypted database file.") ); + +// General TW +TSS_REGISTER_ERROR( eTWHelpInvalidModeSwitch(), _T("Invalid mode parameter to help: ") ); +TSS_REGISTER_ERROR( eTWInitialization(), _T("Tripwire initialization error.") ); +TSS_REGISTER_ERROR( eTWInvalidReportLevel(), _T("Invalid reporting level specified.\nValid levels: [0-4]\n") ); +TSS_REGISTER_ERROR( eTWInvalidReportLevelCfg(), _T("Invalid reporting level in configuration file\nValid levels: [0-4]\n") ); +TSS_REGISTER_ERROR( eTWInvalidPortNumber(), _T("Invalid SMTP port number.\nValid ports: [0-65535]\n") ); +TSS_REGISTER_ERROR( eTWInvalidTempDirectory(), _T("Cannot access temp directory.") ); + +// GMMS +TSS_REGISTER_ERROR( eGmmsError(), _T("GMMS error.") ); +TSS_REGISTER_ERROR( eGmmsCouldntOpenPipe(), _T("GMMS executable not found: ") ); +TSS_REGISTER_ERROR( eGmmsCouldntWritePipe(), _T("There was a problem writing to gmms: ") ); +TSS_REGISTER_ERROR( eGmmsCmdFailed(), _T("GMMS exited with non-zero status: ") ); + +TSS_END_ERROR_REGISTRATION() diff --git a/src/tripwire/tripwireerrors.h b/src/tripwire/tripwireerrors.h new file mode 100644 index 0000000..d3be484 --- /dev/null +++ b/src/tripwire/tripwireerrors.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: tripwireerrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __TRIPWIREERRORS_H +#define __TRIPWIREERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( tripwire ) + +#endif//__TRIPWIREERRORS_H + diff --git a/src/tripwire/tripwiremain.cpp b/src/tripwire/tripwiremain.cpp new file mode 100644 index 0000000..9abb483 --- /dev/null +++ b/src/tripwire/tripwiremain.cpp @@ -0,0 +1,319 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tripwiremain.cpp + +#include "stdtripwire.h" + + +#include "core/debug.h" +#include "core/error.h" +#include "tw/twinit.h" +#include "tw/twutil.h" +#include "twcmdline.h" +#include "core/cmdlineparser.h" +#include "tw/configfile.h" +#include "core/errorbucketimpl.h" +#include "core/usernotifystdout.h" +#include "core/timebomb.h" +#include // for auto_ptr +#include +#include + +#include "tw/twstrings.h" +#include "tripwirestrings.h" +#include "tripwire.h" // package initialization + +#include "fco/fcogenre.h" +#include "fco/genreswitcher.h" + +#if IS_UNIX +#include "core/unixfsservices.h" +#include +#else +#error Who the hell am I? +#endif + +static TSTRING util_GetWholeCmdLine( int argc, const TCHAR *argv[] ); + +/////////////////////////////////////////////////////////////////////////////// +// global new() and delete() overrides -- this is done to do performance testing +/////////////////////////////////////////////////////////////////////////////// +/* +#ifdef _DEBUG +#if defined(HAVE_MALLOC_H) +#include +#endif +static int32 gCurAlloc=0, + gMaxAlloc=0; +void* operator new(size_t size) +{ + gCurAlloc += size; + if(gCurAlloc > gMaxAlloc) + gMaxAlloc = gCurAlloc; + return malloc(size); +} +void operator delete(void* addr) +{ + gCurAlloc -= 4; + free (addr); +} +#endif //_DEBUG +*/ + +/////////////////////////////////////////////////////////////////////////////// +// terminate and unexpected handlers +// TODO: move these to a common library +/////////////////////////////////////////////////////////////////////////////// +void tw_terminate_handler() +{ + fputs("### Internal Error.\n### Terminate Handler called.\n### Exiting...\n", stderr); + _exit(8); +} + +void tw_unexpected_handler() +{ + fputs("### Internal Error.\n### Unexpected Exception Handler called.\n### Exiting...\n", stderr); + _exit(8); +} + +/////////////////////////////////////////////////////////////////////////////// +// main +/////////////////////////////////////////////////////////////////////////////// +int __cdecl _tmain( int argc, const TCHAR* argv[ ], const TCHAR* envp[ ] ) +{ + + if (TimeBombExploded()) + return 8; + + int ret = 0; + + cTWInit twInit; + + + try + { + // set unexpected and terminate handlers + // Note: we do this before Init() in case it attempts to call these handlers + // TODO: move this into the Init() routine + EXCEPTION_NAMESPACE set_terminate(tw_terminate_handler); + EXCEPTION_NAMESPACE set_unexpected(tw_unexpected_handler); + + // Initialization + // + twInit.Init( argv[0] ); + TSS_Dependency( cTripwire ); + + // set up the debug output + cDebug::SetDebugLevel( cDebug::D_DEBUG/*D_DETAIL*//*D_NEVER*/ ); + + + // first, get the right mode... + std::auto_ptr pMode(cTWCmdLine::GetMode(argc, argv)); + if(! pMode.get()) + { + // no valid mode passed; GetMode will display an appropriate string (include usage statement) + ret = 8; + goto exit; + } + + // if version was requested, output version string and exit + if (pMode.get()->GetModeID() == cTWCmdLine::MODE_VERSION) + { + TCOUT << TSS_GetString( cTW, tw::STR_VERSION_LONG) << std::endl; + ret = 0; + goto exit; + } + + // process the command line + cCmdLineParser cmdLine; + pMode->InitCmdLineParser(cmdLine); + try + { + cmdLine.Parse(argc, argv); + } + catch( eError& e ) + { + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + + ret = 8; + goto exit; + } + + TSTRING commandLine = util_GetWholeCmdLine( argc, argv ); + + #if IS_UNIX + // erase the command line + // TODO: it might be a good idea to move this to cTWUtil + int i; + for (i = 1; i < argc; ++i) + memset((char*)argv[i], 0, strlen(argv[i])*sizeof(TCHAR)); + #endif + + cCmdLineIter iter(cmdLine); + if (iter.SeekToArg(cTWCmdLine::HELP)) + { + TCOUT << TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + // + //Since --help was passed, exit after emitting a mode-specific usage statement. + TCOUT << pMode->GetModeUsage(); + ret = 8; + goto exit; + } + + if (iter.SeekToArg(cTWCmdLine::VERBOSE)) + { + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + } + + // open up the config file, possibly using the passed in path + cConfigFile config; + TSTRING strConfigFile; + cErrorReporter errorReporter; + + if( pMode->GetModeID() != cTWCmdLine::MODE_HELP ) + { + try + { + //open cfg file + cTWUtil::OpenConfigFile(config, cmdLine, cTWCmdLine::CFG_FILE, errorReporter, strConfigFile); + } + catch (eError& error) + { + TSTRING extra; + extra += TSS_GetString( cTW, tw::STR_NEWLINE); + extra += TSS_GetString( cTW, tw::STR_ERR_TWCFG_CANT_READ); + + cTWUtil::PrintErrorMsg( error, extra ); + ret = 8; + goto exit; + } + } + + // ok, now we can initialize the mode object and have it execute + pMode->SetCmdLine( commandLine ); + + pMode->SetConfigFile( strConfigFile ); + + if(! pMode->Init(config, cmdLine)) + { + TCERR << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + ret = 8; + goto exit; + } + + ret = pMode->Execute(&twInit.errorQueue); + + }//end try block + + catch (eError& error) + { + cTWUtil::PrintErrorMsg(error); + ASSERT(false); + ret = 8; + } + + catch (std::bad_alloc e) + { + // Note: We use fputs rather than TCERR as it will probably require the + // least amount of memory to do its thing. If we ran out of memory we + // need to do everything we can to get this string out to the user. + fputs("*** Fatal exception: Out of memory\n", stderr); + fputs("*** Exiting...\n", stderr); + ret = 8; + } + + catch (std::exception e) + { + TCERR << _T("*** Fatal exception: "); + std::cerr << e.what() << std::endl; + TCERR << _T("*** Exiting...\n"); + ret = 8; + } + + /* + catch (...) + { + TCERR << _T("*** Fatal exception occurred.\n"); + TCERR << _T("*** Exiting...\n"); + ret = 8; + } + */ + +exit: + + + // print out the max memory usage... +/* +#ifdef _DEBUG + TCOUT << _T("Maximum memory footprint = ") << gMaxAlloc << std::endl; +#endif +*/ + + + return ret; + +} //end MAIN + +static TSTRING util_GetWholeCmdLine( int argc, const TCHAR *argv[] ) +{ + TSTRING tstrRet; + + bool wipeNextItem = false; + + for( int i = 0; i < argc; i++ ) + { + if (wipeNextItem) + { + tstrRet += _T("***** "); + wipeNextItem = false; + } + else + { + tstrRet += argv[i]; + tstrRet += _T(" "); + + // Passwords passed on the command line are not saved + if (_tcsncmp(argv[i], _T("-P"), 2) == 0 || + _tcsncmp(argv[i], _T("-Q"), 2) == 0 || + _tcscmp(argv[i], _T("--local-passphrase")) == 0 || + _tcscmp(argv[i], _T("--site-passphrase")) == 0) + { + wipeNextItem = true; + } + } + } + + return( tstrRet ); +} + diff --git a/src/tripwire/tripwiremsg.h b/src/tripwire/tripwiremsg.h new file mode 100644 index 0000000..f6dbb95 --- /dev/null +++ b/src/tripwire/tripwiremsg.h @@ -0,0 +1,134 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tripwiremsg.mc +// +// This file (tripwiremsg.mc) is the source for tripwire.exe messages. You +// may be reading these comments in tripwiremsg.h, in which case you are reading +// an output file from mc.exe. +// +// This is compiled by the dev studio utility mc.exe to produce the following files: +// +// tripwiremsg.h +// tripwiremsg.rc +// MSG00001.bin +// +// The tripwiremsg.rc file is included in the tripwire resource script "Script1.rc". +// This causes the file MSG00001.bin to be included as a binary resrouce in the final +// executable. +// +// All of this is done to support using Tripwire as an event source for Event Logging. +// In general .mc files such as this are used to support custom strings for the +// FormatMessage() WinAPI. The event viewer requires this mechanism for event strings. +// +// We are sort of cheating here. By having each string be "%1", we can have any string +// we pass to ReportEvent() be the entire Event Log message. Microsoft discourages this +// as it makes localization difficult (you can't just provide a new rc file with +// all of the localized versions of the strings). However, we have chosen to handle the +// localization issues by localizing the strings in the various tripwirestrings files. +// +// To recompile this files into the files listed above run: +// +// mc tripwiremsg.mc +// +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: MSG_TRIPWIRE_GENERIC_SUCCESS +// +// MessageText: +// +// %1 +// +#define MSG_TRIPWIRE_GENERIC_SUCCESS 0x00000001L + +// +// MessageId: MSG_TRIPWIRE_GENERIC_INFO +// +// MessageText: +// +// %1 +// +#define MSG_TRIPWIRE_GENERIC_INFO 0x40000001L + +// +// MessageId: MSG_TRIPWIRE_GENERIC_WARNING +// +// MessageText: +// +// %1 +// +#define MSG_TRIPWIRE_GENERIC_WARNING 0x80000001L + +// +// MessageId: MSG_TRIPWIRE_GENERIC_ERROR +// +// MessageText: +// +// %1 +// +#define MSG_TRIPWIRE_GENERIC_ERROR 0xC0000001L + + diff --git a/src/tripwire/tripwirestrings.cpp b/src/tripwire/tripwirestrings.cpp new file mode 100644 index 0000000..4bc4828 --- /dev/null +++ b/src/tripwire/tripwirestrings.cpp @@ -0,0 +1,300 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tripwirestrings.cpp +// +#include "stdtripwire.h" +#include "tripwirestrings.h" + + +#ifdef GMMS +#define GMMS_OPTION _T(" -g --gmms\n") +#define GMMS_VERBOSITY_OPTION _T(" -b 1|2 --gmms-verbosity 1|2\n") +#else +#define GMMS_OPTION +#define GMMS_VERBOSITY_OPTION +#endif + +#if IS_UNIX +#define MAPI_OPTION +#endif + +TSS_BeginStringtable( cTripwire ) + + TSS_StringEntry( tripwire::STR_TRIPWIRE_VERSION, _T("tripwire: File integrity assessment application.\n")), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_USAGE_SUMMARY, + _T("Usage:\n") + _T("\n") + _T("Database Initialization: tripwire [-m i|--init] [options]\n") + _T("Integrity Checking: tripwire [-m c|--check] [object1 [object2...]]\n") + _T("Database Update: tripwire [-m u|--update]\n") + _T("Policy Update: tripwire [-m p|--update-policy] policyfile.txt\n") + _T("Test: tripwire [-m t|--test] --email address\n") + _T("\n") + _T("Type 'tripwire [mode] --help' OR\n") + _T("'tripwire --help mode [mode...]' OR\n") + _T("'tripwire --help all' for extended help\n") + ), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_HELP_INIT, + _T("Database Initialization mode:\n") + _T(" -m i --init\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -d database --dbfile database\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -e --no-encryption\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("The -L and -e options are mutually exclusive.\n") + _T("The -P and -e options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_HELP_CHECK, + _T("Integrity Check mode:\n") + _T(" -m c --check\n") + _T(" -I --interactive\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -d database --dbfile database\n") + _T(" -r report --twrfile report\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -n --no-tty-output\n") + _T(" -V editor --visual editor\n") + _T(" -E --signed-report\n") + _T(" -R rule --rule-name rule\n") + _T(" -l {level | name} --severity {level | name}\n") + _T(" -x section --section section\n") + _T(" -i list --ignore list\n") + _T(" -M --email-report\n") + _T(" -t { 0|1|2|3|4 } --email-report-level { 0|1|2|3|4 }\n") + + // Only insert the description of these two options if GMMS is defined. + // Otherwise these two lines will be blank. You cannot have #ifdef in + // the middle of this big concatenated string. + GMMS_OPTION + GMMS_VERBOSITY_OPTION + + _T("[object1 [object2...]]\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("The -l and -R options are mutually exclusive.\n") + _T("The -P option is only valid with -E or -I.\n") + _T("The -V option is only valid with -I.\n") + _T("The -t option is only valid with -M.\n") + _T("Specifying objects overrides the -l and -R options.\n") + _T("\n") + ), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_HELP_UPDATE, + _T("Database Update mode:\n") + _T(" -m u --update\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -d database --dbfile database\n") + _T(" -r report --twrfile report\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -V editor --visual editor\n") + _T(" -a --accept-all\n") + _T(" -Z {low | high} --secure-mode {low | high}\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("The -a and -V options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_HELP_UPDATE_POLICY, + _T("Policy Update mode:\n") + _T(" -m p --update-policy\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -d database --dbfile database\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T(" -Z {low | high} --secure-mode {low | high}\n") + _T("policyfile.txt\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( tripwire::STR_TRIPWIRE_HELP_TEST, + _T("Test mode:\n") + _T(" -m t --test\n") + _T(" -e user@domain.com --email user@domain.com\n") + _T("\n") + // Only insert the MAPI option under NT. + MAPI_OPTION + _T("Only one address may be entered.\n") + _T("\n") + ), + + + TSS_StringEntry( tripwire::STR_INTEGRITY_CHECK, _T("Performing integrity check...\n")), + TSS_StringEntry( tripwire::STR_IC_SUCCESS, _T("Integrity check complete.\n")), + TSS_StringEntry( tripwire::STR_IC_FILES, _T("Integrity checking objects specified on command line...\n")), + TSS_StringEntry( tripwire::STR_CHECKING_SPECS_NAMED, _T("Checking rules named: ")), + TSS_StringEntry( tripwire::STR_CHECKING_GENRE, _T("Checking section %s only.\n")), + TSS_StringEntry( tripwire::STR_IC_SEVERITY_LEVEL, _T("Checking rules at or above severity level: ")), + TSS_StringEntry( tripwire::STR_IC_IGNORING_SEVERITY, _T("Ignoring rule %s (severity %d)\n")), + TSS_StringEntry( tripwire::STR_IC_IGNORING_SEV_NUM, _T("Warning: Severity number specified on command line will be ignored.\n")), + TSS_StringEntry( tripwire::STR_IC_IGNORING_SEV_NAME, _T("Warning: Severity name specified on command line will be ignored.\n")), + TSS_StringEntry( tripwire::STR_IC_IGNORING_RULE_NAME, _T("Warning: Rule name specified on command line will be ignored.\n")), + TSS_StringEntry( tripwire::STR_IC_IGNORING_GENRE_NAME, _T("Warning: Section name specified on command line will be ignored.\n")), + TSS_StringEntry( tripwire::STR_IC_NOEMAIL_SENT, _T("Nothing to report, no email sent.\n")), + TSS_StringEntry( tripwire::STR_NO_EMAIL_RECIPIENTS, _T("No email recipients specified, no email sent.\n")), + + TSS_StringEntry( tripwire::STR_PU_PROCESSING_GENRE, _T("======== Policy Update: Processing section %s.\n") ), + TSS_StringEntry( tripwire::STR_PU_INTEGRITY_CHECK, _T("======== Step 1: Gathering information for the new policy.\n") ), + TSS_StringEntry( tripwire::STR_PU_UPDATE_DB, _T("======== Step 2: Updating the database with new objects.\n") ), + TSS_StringEntry( tripwire::STR_PU_PRUNING, _T("======== Step 3: Pruning unneeded objects from the database.\n") ), + TSS_StringEntry( tripwire::STR_PU_ADDING_GENRE, _T("======== Policy Update: Adding section %s.\n") ), + TSS_StringEntry( tripwire::STR_PU_BAD_PROPS, _T("Conflicting properties for object ") ), + TSS_StringEntry( tripwire::STR_PROCESSING_GENRE, _T("*** Processing %s ***\n") ), + + // gmms reporting, these strings are for the gmms command line + TSS_StringEntry( tripwire::STR_GMMS_START, _T("alert Tripwire: ")), + TSS_StringEntry( tripwire::STR_GMMS_END, _T(")")), + TSS_StringEntry( tripwire::STR_GMMS_VERBOSITY1A, _T(", Violations found (")), + TSS_StringEntry( tripwire::STR_GMMS_VERBOSITY1B, _T("), Max severity (")), + TSS_StringEntry( tripwire::STR_GMMS_VERBOSITY2A, _T(", Rule Violated (")), + TSS_StringEntry( tripwire::STR_GMMS_VERBOSITY2B, _T("), File (")), + TSS_StringEntry( tripwire::STR_GMMS_VERBOSITY2C, _T("), Severity (")), + + + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR1, _T("A recipient matched more than one of the recipient descriptor structures. No message was sent.\n(MAPI error: MAPI_E_AMBIGUOUS_RECIPIENT)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR2, _T("The specified attachment was not found. No message was sent.\n(MAPI error: MAPI_E_ATTACHMENT_NOT_FOUND)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR3, _T("The specified attachment could not be opened. No message was sent.\n(MAPI error: MAPI_E_ATTACHMENT_OPEN_FAILURE)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR4, _T("The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.\n(MAPI error: MAPI_E_BAD_RECIPTYPE)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR5, _T("One or more unspecified errors occurred. No message was sent.\n(MAPI error: MAPI_E_FAILURE)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR6, _T("There was insufficient memory to proceed. No message was sent.\n(MAPI error: MAPI_E_INSUFFICIENT_MEMORY)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR7, _T("One or more recipients were invalid or did not resolve to any address.\n(MAPI error: MAPI_E_INVALID_RECIPS)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR8, _T("There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.\n(MAPI error: MAPI_E_LOGIN_FAILURE)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR9, _T("The text in the message was too large. No message was sent.\n(MAPI error: MAPI_E_TEXT_TOO_LARGE)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR10, _T("There were too many file attachments. No message was sent.\n(MAPI error: MAPI_E_TOO_MANY_FILES)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR11, _T("There were too many recipients. No message was sent.\n(MAPI error: MAPI_E_TOO_MANY_RECIPIENTS)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR12, _T("A recipient did not appear in the address list. No message was sent.\n(MAPI error: MAPI_E_UNKNOWN_RECIPIENT)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR13, _T("The user canceled one of the dialog boxes. No message was sent.\n(MAPI error: MAPI_E_USER_ABORT)")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR14, _T("MAPI returned a unrecognized error (")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR14_1, _T(").")), + + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_SERVER, _T("Server: ")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_SERVER_RETURNED_ERROR, _T("Error Number:")), + TSS_StringEntry( tripwire::STR_ERR2_MAIL_MESSAGE_COMMAND, _T("Command: ")), + + // + // Tripwire Command Line + // + TSS_StringEntry( tripwire::STR_ERR_IC_EMAIL_AND_FILES, _T("Email reporting cannot be specified when checking a list of objects.")), + TSS_StringEntry( tripwire::STR_ERR_NO_MAIL_METHOD, _T("No mail method specified in configuration file.")), + TSS_StringEntry( tripwire::STR_ERR_INVALID_MAIL_METHOD, _T("Invalid mail method in configuration file.")), + TSS_StringEntry( tripwire::STR_ERR_MAPI_NOT_SUPPORTED, _T("Configuration option MAILMETHOD=MAPI is not supported on this platform.")), + TSS_StringEntry( tripwire::STR_ERR_MISSING_MAILPROGRAM, _T("Mail method is set to SENDMAIL but MAILPROGRAM was not defined in configuration file")), + TSS_StringEntry( tripwire::STR_ERR_NO_TEST_MODE, _T("No test area specified.")), + TSS_StringEntry( tripwire::STR_GENERATING_DB, _T("Generating the database...\n")), + TSS_StringEntry( tripwire::STR_INIT_SUCCESS, _T("The database was successfully generated.\n")), + TSS_StringEntry( tripwire::STR_ERR2_DIFFERENT_USERS1, _T("Created by: ")), + TSS_StringEntry( tripwire::STR_ERR2_DIFFERENT_USERS2, _T("\nCurrent user: ")), + TSS_StringEntry( tripwire::STR_ERR_IC_NO_SPECS_LEFT, _T("No rules to check for section %s.\n")), + TSS_StringEntry( tripwire::STR_ERR_BAD_PARAM, _T("Invalid parameter.")), + TSS_StringEntry( tripwire::STR_ERR_UPDATE_ED_LAUNCH, _T("Interactive Update failed.")), + TSS_StringEntry( tripwire::STR_REPORT_EMPTY, _T("The report contains no new data, the database will not be updated.\n")), + TSS_StringEntry( tripwire::STR_DB_NOT_UPDATED, _T("The database was not updated. ")), + TSS_StringEntry( tripwire::STR_ERR_POL_UPDATE, _T("Policy update failed; policy and database files were not altered.")), + TSS_StringEntry( tripwire::STR_IGNORE_PROPS, _T("Ignoring properties: ")), + TSS_StringEntry( tripwire::STR_ERR_ILLEGAL_MODE_HELP, _T("Error, mode does not exist: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_IDENT, _T("tripwire")), + TSS_StringEntry( tripwire::STR_SYSLOG_INIT_MSG, _T("Database initialized: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_IC_MSG, _T("Integrity Check Complete: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_UP_MSG, _T("Database Update Complete: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_POLUP_MSG, _T("Policy Update Complete: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_INIT_FAIL_MSG, _T("Database initialization Failed: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_IC_FAIL_MSG, _T("Integrity Check Failed: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_UP_FAIL_MSG, _T("Database Update Failed: ")), + TSS_StringEntry( tripwire::STR_SYSLOG_POLUP_FAIL_MSG, _T("Policy Update Failed: ")), + + + // + // email testing + // + TSS_StringEntry( tripwire::STR_TEST_EMAIL_TO, _T("Sending a test message to:")), + TSS_StringEntry( tripwire::STR_TEST_EMAIL_SUBJECT, _T("Test email message from Tripwire")), + TSS_StringEntry( tripwire::STR_TEST_EMAIL_BODY, _T("If you receive this message, email notification from tripwire is working correctly.")), + // + // email reporting + // + TSS_StringEntry( tripwire::STR_EMAIL_SUBJECT_REPORT_1, _T("Tripwire report (violation count ")), + TSS_StringEntry( tripwire::STR_EMAIL_SUBJECT_REPORT_2, _T(") (max severity ")), + TSS_StringEntry( tripwire::STR_EMAIL_SUBJECT_REPORT_3, _T(")")), + TSS_StringEntry( tripwire::STR_EMAIL_REPORT_TO, _T("Emailing the report to:")), + TSS_StringEntry( tripwire::STR_EMAIL_FROM, _T("tripwire@")), + TSS_StringEntry( tripwire::STR_EMAIL_BEGIN, _T("Beginning email reporting...")), + TSS_StringEntry( tripwire::STR_EMAIL_OK_BODY, _T("Rules with no violations or errors:")), + TSS_StringEntry( tripwire::STR_EMAIL_NO_RECIPIENTS, _T("No email recipients specified in policy file; no email sent.")), + TSS_StringEntry( tripwire::STR_EMAIL_OK_TO, _T("Emailing \"no violations\" message to:")), + TSS_StringEntry( tripwire::STR_EMAIL_SUBJECT_OK, _T("Tripwire found no violations")), + TSS_StringEntry( tripwire::STR_ERR_EMAIL_REPORT, _T("Email reporting failed.")), + TSS_StringEntry( tripwire::STR_ERR_EMAIL_TEST, _T("Email test failed.")), + // + // Gmms errors + // + TSS_StringEntry( tripwire::STR_ERR_BAD_GMMS_VERBOSITY, _T("Error: gmms verbosity must be 1 or 2. ")), + TSS_StringEntry( tripwire::STR_ERR_GMMS_VERBOSITY_ONLY, _T("Error: --gmms-verbosity specified without --gmms. ")), + + + TSS_StringEntry( tripwire::STR_NOTIFY_PROCESSING, _T("Processing: ")), + TSS_StringEntry( tripwire::STR_NOTIFY_CHECKING, _T("Checking: ")), + TSS_StringEntry( tripwire::STR_NOTIFY_CHECKING_RULE, _T("Checking rule: ")), + TSS_StringEntry( tripwire::STR_NOTIFY_DB_CHANGING, _T("Database update: Modifying record ")), + TSS_StringEntry( tripwire::STR_NOTIFY_DB_ADDING, _T("Database update: Adding record ")), + TSS_StringEntry( tripwire::STR_NOTIFY_DB_REMOVING, _T("Database update: Removing record ")), + TSS_StringEntry( tripwire::STR_NOTIFY_GEN_SIG, _T("Generating information for: ")), + +TSS_EndStringtable( cTripwire ) + diff --git a/src/tripwire/tripwirestrings.h b/src/tripwire/tripwirestrings.h new file mode 100644 index 0000000..cde0168 --- /dev/null +++ b/src/tripwire/tripwirestrings.h @@ -0,0 +1,177 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// tripwirestrings.h +// +#ifndef __TRIPWIRESTRINGS_H +#define __TRIPWIRESTRINGS_H + +#include "tripwire.h" + +TSS_BeginStringIds( tripwire ) + + STR_TRIPWIRE_VERSION, + STR_TRIPWIRE_HELP_INIT, + STR_TRIPWIRE_HELP_CHECK, + STR_TRIPWIRE_HELP_UPDATE, + STR_TRIPWIRE_HELP_UPDATE_POLICY, + STR_TRIPWIRE_HELP_TEST, + STR_TRIPWIRE_USAGE_SUMMARY, + STR_INTEGRITY_CHECK, + STR_IC_SUCCESS, + STR_IC_FILES, + STR_CHECKING_SPECS_NAMED, + STR_CHECKING_GENRE, + STR_IC_SEVERITY_LEVEL, + STR_IC_IGNORING_SEVERITY, + STR_IC_IGNORING_SEV_NUM, + STR_IC_IGNORING_SEV_NAME, + STR_IC_IGNORING_RULE_NAME, + STR_IC_IGNORING_GENRE_NAME, + STR_IC_NOEMAIL_SENT, + STR_NO_EMAIL_RECIPIENTS, + STR_PU_PROCESSING_GENRE, + STR_PU_INTEGRITY_CHECK, + STR_PU_UPDATE_DB, + STR_PU_PRUNING, + STR_PU_ADDING_GENRE, + STR_PU_BAD_PROPS, + STR_PROCESSING_GENRE, + + // + // GMMS specific + // + STR_GMMS_START, + STR_GMMS_END, + STR_GMMS_VERBOSITY1A, + STR_GMMS_VERBOSITY1B, + STR_GMMS_VERBOSITY2A, + STR_GMMS_VERBOSITY2B, + STR_GMMS_VERBOSITY2C, + + // + // MAPI error messages + // + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR1, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR2, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR3, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR4, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR5, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR6, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR7, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR8, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR9, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR10, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR11, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR12, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR13, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR14, + STR_ERR2_MAIL_MESSAGE_MAPI_SEND_ERRROR14_1, + + STR_ERR2_MAIL_MESSAGE_SERVER, + STR_ERR2_MAIL_MESSAGE_SERVER_RETURNED_ERROR, + STR_ERR2_MAIL_MESSAGE_COMMAND, + + // + // Tripwire Command Line + // + STR_ERR_IC_EMAIL_AND_FILES, + STR_ERR_NO_MAIL_METHOD, + STR_ERR_INVALID_MAIL_METHOD, + STR_ERR_MAPI_NOT_SUPPORTED, + STR_ERR_MISSING_MAILPROGRAM, + STR_ERR_NO_TEST_MODE, + STR_GENERATING_DB, + STR_INIT_SUCCESS, + STR_ERR2_DIFFERENT_USERS1, + STR_ERR2_DIFFERENT_USERS2, + STR_ERR_IC_NO_SPECS_LEFT, + STR_ERR_BAD_PARAM, + STR_ERR_UPDATE_ED_LAUNCH, + STR_REPORT_EMPTY, + STR_DB_NOT_UPDATED, + STR_ERR_POL_UPDATE, + STR_IGNORE_PROPS, + STR_ERR_ILLEGAL_MODE_HELP, + STR_SYSLOG_IDENT, + STR_SYSLOG_INIT_MSG, + STR_SYSLOG_IC_MSG, + STR_SYSLOG_UP_MSG, + STR_SYSLOG_POLUP_MSG, + STR_SYSLOG_INIT_FAIL_MSG, + STR_SYSLOG_IC_FAIL_MSG, + STR_SYSLOG_UP_FAIL_MSG, + STR_SYSLOG_POLUP_FAIL_MSG, + + // + // email testing + // + STR_TEST_EMAIL_TO, + STR_TEST_EMAIL_SUBJECT, + STR_TEST_EMAIL_BODY, + // + // email reporting + // + STR_EMAIL_SUBJECT_REPORT_1, + STR_EMAIL_SUBJECT_REPORT_2, + STR_EMAIL_SUBJECT_REPORT_3, + STR_EMAIL_REPORT_TO, + STR_EMAIL_FROM, + STR_EMAIL_BEGIN, + STR_EMAIL_OK_BODY, + STR_EMAIL_NO_RECIPIENTS, + STR_EMAIL_OK_TO, + STR_EMAIL_SUBJECT_OK, + STR_ERR_EMAIL_REPORT, + STR_ERR_EMAIL_TEST, + + + // + // Gmms errors + // + STR_ERR_BAD_GMMS_VERBOSITY, + STR_ERR_GMMS_VERBOSITY_ONLY, + + + STR_NOTIFY_PROCESSING, + STR_NOTIFY_CHECKING, + STR_NOTIFY_CHECKING_RULE, + STR_NOTIFY_DB_CHANGING, + STR_NOTIFY_DB_ADDING, + STR_NOTIFY_DB_REMOVING, + STR_NOTIFY_GEN_SIG + +TSS_EndStringIds( tripwire ) + + +#endif + diff --git a/src/tripwire/tripwireutil.cpp b/src/tripwire/tripwireutil.cpp new file mode 100644 index 0000000..3950933 --- /dev/null +++ b/src/tripwire/tripwireutil.cpp @@ -0,0 +1,148 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// tripwireutil.cpp +#include "stdtripwire.h" +#include "tripwireutil.h" +#include "tw/fcodatabasefile.h" +#include "fco/fcospeclist.h" +#include "fco/fcopropcalc.h" +#include "fco/iterproxy.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" +#include "fco/fcopropdisplayer.h" +#include "fco/fconame.h" +#include "tw/dbdatasource.h" +#include "tripwirestrings.h" + +// for verbose output +#include "core/usernotify.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" + +/////////////////////////////////////////////////////////////////////////////// +// CalcProps +/////////////////////////////////////////////////////////////////////////////// +void cTripwireUtil::CalcProps( iFCO* pFCO, const iFCOSpec* pSpec, iFCOPropCalc* pCalc, iFCOPropDisplayer* pPD ) +{ + // verbose output... + TW_NOTIFY_VERBOSE( _T("--- %s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_GEN_SIG ).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( pFCO->GetName() ).c_str() ); + + + const cFCOPropVector& propsToCalc = pSpec->GetPropVector(pSpec->GetSpecMask(pFCO)); + // set the appropriate property mask for this fco + pCalc->SetPropVector(propsToCalc); + // do the calculation + pFCO->AcceptVisitor(pCalc->GetVisitor()); + // + // invalidate unneeded properties.... + // I want to invalidate everything that is in the fco but not in the spec... + // + cFCOPropVector propsToInvalidate = pFCO->GetPropSet()->GetValidVector(); + propsToInvalidate ^= propsToCalc; + pFCO->GetPropSet()->InvalidateProps( propsToInvalidate ); + // + // load this fco's data into the prop displayer + // + if( pPD ) + pPD->InitForFCO( pFCO ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// RemoveFCOFromDb +/////////////////////////////////////////////////////////////////////////////// +bool cTripwireUtil::RemoveFCOFromDb( cFCOName name, cDbDataSourceIter& dbIter) +{ + cDebug d("cTripwireUtil::RemoveFCOFromDb"); + //cDbDataSourceIter dbIter( &db ); + + // seek to the fco to be removed.. + // + dbIter.SeekToFCO( name, false ); + // + // error if the fco doesn't exist... + // + if( dbIter.Done() || ( ! dbIter.HasFCOData() ) ) + { + return false; + } + else + { + // remove the fco data... + // + d.TraceDebug(_T(">>> Removing FCO %s\n"), dbIter.GetName().AsString().c_str()); + dbIter.RemoveFCOData() ; + if( ! dbIter.CanDescend() ) + { + // note that this is not sufficient to remove all unused nodes from the database... + // + d.TraceDebug(_T(">>> Removing Database Node %s\n"), dbIter.GetName().AsString().c_str()); + dbIter.RemoveFCO(); + } + // + // get rid of all the empty parents above me... + // TODO -- is this the right thing to do all the time? + // + while( ! dbIter.AtRoot() ) + { + cFCOName parentName = dbIter.GetParentName(); + dbIter.Ascend(); + dbIter.SeekTo( parentName.GetShortName() ); + ASSERT( ! dbIter.Done() ); + if( (! dbIter.Done()) && (dbIter.CanRemoveChildArray()) ) + { + dbIter.RemoveChildArray(); + // + // and, remove this node if there is no fco data... + // + if( ! dbIter.HasFCOData() ) + { + d.TraceDebug(_T(">>> Removing Database Node %s\n"), dbIter.GetName().AsString().c_str()); + dbIter.RemoveFCO(); + } + else + break; + } + else + break; + } + + } + + return true; +} + + diff --git a/src/tripwire/tripwireutil.h b/src/tripwire/tripwireutil.h new file mode 100644 index 0000000..d5887c6 --- /dev/null +++ b/src/tripwire/tripwireutil.h @@ -0,0 +1,68 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// tripwireutil.h +// +// utility functions for the top-level tripwire functionality implemented in +// cTripwire +#ifndef __TRIPWIREUTIL_H +#define __TRIPWIREUTIL_H + +class iFCO; +class iFCOSpec; +class iFCOPropCalc; +class iFCOPropDisplayer; +class cFCOName; +class cDbDataSourceIter; +class cHierDatabase; + +class cTripwireUtil +{ +public: + + static void CalcProps( iFCO* pFCO, const iFCOSpec* pSpec, iFCOPropCalc* pCalc, iFCOPropDisplayer* pPD ); + // this method calculates exactly the properties specified by pSpec (invalidating any extra ones) + // for iFCO. It is OK to pass NULL for pPD if you don't want the property calculator run over the fco; + // otherwise, InitForFCO() is called after the property calculation is done. + // TODO -- I should determine what exceptions will come up from this and document it + + static bool RemoveFCOFromDb( cFCOName name, cDbDataSourceIter& dbIter); + // removes the named fco from the passed in database. This asserts that the iterator is not done, + // and gracefully handles the case where there is no fco data associated with the current node. + // also, if there is an empty subtree below this node (ie -- hier nodes with no FCO data) this method + // will remove them from the database. + // this returns true if fco data was actually removed from the database. +}; + + +#endif //__TRIPWIREUTIL_H + diff --git a/src/tripwire/twcmdline.cpp b/src/tripwire/twcmdline.cpp new file mode 100644 index 0000000..6d50bf3 --- /dev/null +++ b/src/tripwire/twcmdline.cpp @@ -0,0 +1,2800 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twcmdline.cpp +#include "stdtripwire.h" +#include "twcmdline.h" +#include "core/cmdlineparser.h" +#include "tw/configfile.h" + +#include "core/serializerimpl.h" // cSerializerImpl +#include "core/archive.h" // cArchive and friends +#include "fco/fcospeclist.h" // cFCOSpecList +#include "tripwirestrings.h" // tripwire.exe specific strings +#include "twcrypto/keyfile.h" // cKeyFile -- used for encryption +#include "tw/twutil.h" +#include "twcmdlineutil.h" // utility functions for the cmd line +#include "tw/fcoreport.h" // for reports +#include "tw/textreportviewer.h" // text report viewer +#include "core/usernotify.h" // for notifying the user of events +#include "tw/fcoreportutil.h" // for finalizing report +#include "tw/fcodatabaseutil.h" // for finalizing database +#include "tw/headerinfo.h" // for finalizing database +#include "fco/fcopropdisplayer.h" +#include "tw/systeminfo.h" +#include "tw/filemanipulator.h" +#include "fco/twfactory.h" +#include "mailmessage.h" // used for email reporting +#include "fco/genrespeclist.h" +#include "core/twlimits.h" // for severity limits +#include "core/errorgeneral.h" +#include "core/corestrings.h" +#include "tw/twerrors.h" +#include "core/stringutil.h" +#include "util/fileutil.h" +#include "tw/twstrings.h" +#include "syslog_trip.h" +#include +#include "fco/parsergenreutil.h" // this is needed to figure out if a path is fully qualified for the current genre. +#include "tw/fcodatabasefile.h" +#include "fco/genreswitcher.h" +#include "generatedb.h" +#include "integritycheck.h" +#include "updatedb.h" +#include "policyupdate.h" + +#ifdef TW_PROFILE +#include "tasktimer.h" +#endif + +#if IS_UNIX +#include "fs/fsdatasourceiter.h" // for cross file systems flag +#include // for _exit() +#endif + + +//----------------------------------------------------------------------------- +// #defines +//----------------------------------------------------------------------------- + +// this is used to make required condition checking in the Init() functions a little more compact +#define TEST_INIT_REQUIREMENT(t, c, n)\ + if(! t)\ + {\ + cTWUtil::PrintErrorMsg(eTWInitialization(TSS_GetString( c, n ), 0)); \ + return false;\ + } + + +static bool util_GetEditor( TSTRING& strEd ); + +//############################################################################# +// cTWCmdLine +//############################################################################# + + +/////////////////////////////////////////////////////////////////////////////// +// GetMode -- processes the command line arguments and creates an appropriate +// structure for the selected mode, or NULL if an error occurs +/////////////////////////////////////////////////////////////////////////////// +iTWMode* cTWCmdLine::GetMode(int argc, const TCHAR *const * argv) +{ + // note -- it is assumed the executable name is the first parameter + if(argc < 2) + { + TCOUT << TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + + int mode = MODE; + const TCHAR* pcMode; + if(_tcscmp(argv[1], _T("-m")) == 0) + { + if(argc < 3) + { + TCOUT << TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_ERR_NO_MODE) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + pcMode = argv[2]; + if (_tcscmp(argv[2], _T("i")) == 0) + mode = MODE_INIT; + else if (_tcscmp(argv[2], _T("c")) == 0) + mode = MODE_CHECK; + else if (_tcscmp(argv[2], _T("u")) == 0) + mode = MODE_UPDATE_DB; + else if (_tcscmp(argv[2], _T("p")) == 0) + mode = MODE_UPDATE_POL; + else if (_tcscmp(argv[2], _T("t")) == 0) + mode = MODE_TEST; + } + else + { + pcMode = argv[1]; + if (_tcscmp(argv[1], _T("--init")) == 0) + mode = MODE_INIT; + else if (_tcscmp(argv[1], _T("--check")) == 0) + mode = MODE_CHECK; + else if (_tcscmp(argv[1], _T("--update")) == 0) + mode = MODE_UPDATE_DB; + else if (_tcscmp(argv[1], _T("--update-policy")) == 0) + mode = MODE_UPDATE_POL; + else if (_tcscmp(argv[1], _T("--version")) == 0) + mode = MODE_VERSION; + else if (_tcscmp(argv[1], _T("--help")) == 0 || _tcscmp(argv[1], _T("-?")) == 0) + mode = MODE_HELP; + else if (_tcscmp(argv[1], _T("--test")) == 0) + mode = MODE_TEST; + +#ifdef _DEBUG_DB + if (_tcscmp(argv[1], _T("--explore")) == 0) + mode = MODE_EXPLORE; + if (_tcscmp(argv[1], _T("--verifydb")) == 0) + mode = MODE_DEBUG; +#endif + + } + + if(mode == MODE) + { + // unknown mode switch + cDebug d("cTWCmdLine::GetMode"); + d.TraceError(_T("Error: Bad mode switch: %s\n"), pcMode); + TCERR << TSS_GetString( cTW, tw::STR_UNKOWN_MODE_SPECIFIED) + << pcMode << std::endl + << TSS_GetString( cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + + + iTWMode* pRtn = 0; + switch(mode) + { + case cTWCmdLine::MODE_INIT: + pRtn = new cTWModeDbInit; + break; + case cTWCmdLine::MODE_CHECK: + pRtn = new cTWModeIC; + break; + case cTWCmdLine::MODE_UPDATE_DB: + pRtn = new cTWModeDbUpdate; + break; + case cTWCmdLine::MODE_UPDATE_POL: + pRtn = new cTWModePolUpdate; + break; + case cTWCmdLine::MODE_TEST: + pRtn = new cTWModeTest; + break; + case cTWCmdLine::MODE_HELP: + pRtn = new cTWModeHelp; + break; + case cTWCmdLine::MODE_VERSION: + pRtn = new cTWModeVersion; + break; + +//Explore and Debug modes are invisible unless _DEBUG_DB is defined. +#ifdef _DEBUG_DB + case cTWCmdLine::MODE_EXPLORE: + pRtn = new cTWModeExploreDb; + break; + case cTWCmdLine::MODE_DEBUG: + pRtn = new cTWModeDebugDb; + break; +#endif + + default: + ASSERT(false); + } + + return pRtn; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineCommon -- initializes the command line switches common to all +// modes +/////////////////////////////////////////////////////////////////////////////// +static void InitCmdLineCommon(cCmdLineParser& parser) +{ + parser.AddArg(cTWCmdLine::HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::VERBOSE, TSTRING(_T("v")), TSTRING(_T("verbose")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWCmdLine::SILENT, TSTRING(_T("s")), TSTRING(_T("silent")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWCmdLine::SILENT, TSTRING(_T("")), TSTRING(_T("quiet")), cCmdLineParser::PARAM_NONE); + //parser.AddArg(cTWCmdLine::NO_BACKUP, TSTRING(_T("B")), TSTRING(_T("nobackup")), cCmdLineParser::PARAM_NONE); + // this was dropped from 1.5 -- mdb + parser.AddArg(cTWCmdLine::LOCAL_PASSPHRASE, TSTRING(_T("P")), TSTRING(_T("local-passphrase")),cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::POL_FILE, TSTRING(_T("p")), TSTRING(_T("polfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::CFG_FILE, TSTRING(_T("c")), TSTRING(_T("cfgfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::DB_FILE, TSTRING(_T("d")), TSTRING(_T("dbfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWCmdLine::REPORT_FILE, TSTRING(_T("r")), TSTRING(_T("twrfile")), cCmdLineParser::PARAM_ONE); + + // + // mutual exclusions + // + parser.AddMutEx(cTWCmdLine::VERBOSE, cTWCmdLine::SILENT); + +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutConfigInfo -- fills out all the common info with config file information +/////////////////////////////////////////////////////////////////////////////// +static void FillOutConfigInfo(cTWModeCommon* pModeInfo, const cConfigFile& cf) +{ + TSTRING str; + if(cf.Lookup(TSTRING(_T("POLFILE")), str)) + pModeInfo->mPolFile = str; + if(cf.Lookup(TSTRING(_T("DBFILE")), str)) + pModeInfo->mDbFile = str; + if(cf.Lookup(TSTRING(_T("SITEKEYFILE")), str)) + pModeInfo->mSiteKeyFile = str; + if(cf.Lookup(TSTRING(_T("LOCALKEYFILE")), str)) + pModeInfo->mLocalKeyFile = str; + if(cf.Lookup(TSTRING(_T("REPORTFILE")), str)) + pModeInfo->mReportFile = str; + if(cf.Lookup(TSTRING(_T("EDITOR")), str)) + pModeInfo->mEditor = str; + if(cf.Lookup(TSTRING(_T("LATEPROMPTING")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + pModeInfo->mbLatePassphrase = true; + } + if(cf.Lookup(TSTRING(_T("RESETACCESSTIME")), str)) + { + + +#if IS_UNIX + // We do not support reset access time on Unix, so we issue a warning. + // This used to be a fatal error, however this prevents + // cross platform config files. + cTWUtil::PrintErrorMsg(eTWInvalidConfigFileKey(_T("RESETACCESSTIME"), eError::NON_FATAL)); +#endif + + } + if(cf.Lookup(TSTRING(_T("LOOSEDIRECTORYCHECKING")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + pModeInfo->mfLooseDirs = true; + } + + if (cf.Lookup(TSTRING(_T("TEMPDIRECTORY")), str)) { + + if (str.length() == 0) + str = "/tmp/"; + + // make sure we have a trailing slash -- thanks Jarno... + // + if (str[_tcslen(str.c_str())-1] != '/') { + str += '/'; + } + + // make sure it exists... + // + if (access(str.c_str(), F_OK) != 0) { + TSTRING errStr = TSS_GetString( cCore, core::STR_BAD_TEMPDIRECTORY ); + TSTRING tmpStr = _T("Directory: "); + tmpStr += (str + _T("\n")); + tmpStr += errStr; + throw eTWInvalidTempDirectory(tmpStr); + } + else { + iFSServices::GetInstance()->SetTempDirName(str); + } + + } + + if (cf.Lookup(TSTRING(_T("GLOBALEMAIL")), str)) { + + if (str.length() != 0) + pModeInfo->mGlobalEmail = str; + } + + // + // Set the report-viewing level if one has been specified, use + // default level otherwise. + // + if(cf.Lookup(TSTRING(_T("EMAILREPORTLEVEL")), str)) + { + if (_tcsicmp(str.c_str(), _T("0")) == 0) + pModeInfo->mEmailReportLevel = cTextReportViewer::SINGLE_LINE; + else if (_tcsicmp(str.c_str(), _T("1")) == 0) + pModeInfo->mEmailReportLevel = cTextReportViewer::PARSEABLE; + else if (_tcsicmp(str.c_str(), _T("2")) == 0) + pModeInfo->mEmailReportLevel = cTextReportViewer::SUMMARY_ONLY; + else if (_tcsicmp(str.c_str(), _T("3")) == 0) + pModeInfo->mEmailReportLevel = cTextReportViewer::CONCISE_REPORT; + else if (_tcsicmp(str.c_str(), _T("4")) == 0) + pModeInfo->mEmailReportLevel = cTextReportViewer::FULL_REPORT; + else + { + // They specified an illegal level, error. + TSTRING errStr = _T("Invalid Level: "); + errStr += str; + throw eTWInvalidReportLevelCfg( errStr ); + } + } + else + // no level was specified in the configuration file, use default. + pModeInfo->mEmailReportLevel = cTextReportViewer::CONCISE_REPORT; + + + // Decide what mail method should be used to email reports + if(cf.Lookup(TSTRING(_T("MAILMETHOD")), str)) + { + if (_tcsicmp(str.c_str(), _T("SENDMAIL")) == 0) + pModeInfo->mMailMethod = cMailMessage::MAIL_BY_PIPE; + else if (_tcsicmp(str.c_str(), _T("MAPI")) == 0) + pModeInfo->mMailMethod = cMailMessage::MAIL_BY_MAPI; // NT support only + else if( _tcsicmp( str.c_str(), _T("SMTP") ) == 0 ) + pModeInfo->mMailMethod = cMailMessage::MAIL_BY_SMTP; + else + pModeInfo->mMailMethod = cMailMessage::INVALID_METHOD; + } + else + { + pModeInfo->mMailMethod = cMailMessage::NO_METHOD; + } + + // Get the SMTP server + if(cf.Lookup(TSTRING(_T("SMTPHOST")), str)) + pModeInfo->mSmtpHost = str; + else + pModeInfo->mSmtpHost = _T("127.0.0.1"); // this is the default + + // Get the SMTP port number + if(cf.Lookup(TSTRING(_T("SMTPPORT")), str)) + { + int i = _ttoi( str.c_str() ); + if( i < 0 || i > SHRT_MAX ) + throw eTWInvalidPortNumber( str ); + pModeInfo->mSmtpPort = static_cast( i ); + } + else + pModeInfo->mSmtpPort = 25; // this is the default + + // Get the mail program to use if we're piping our email + if(cf.Lookup(TSTRING(_T("MAILPROGRAM")), str)) + pModeInfo->mMailProgram = str; + else + pModeInfo->mMailProgram.erase(); // MAILPROGRAM is not required to be specified + + // Get the mail program to use if we're piping our email + if(cf.Lookup(TSTRING(_T("MAILNOVIOLATIONS")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + pModeInfo->mMailNoViolations = true; + else + pModeInfo->mMailNoViolations = false; + } + else + pModeInfo->mMailNoViolations = true; // MAILPROGRAM is not required to be specified + + // SYSLOG reporting + if(cf.Lookup(TSTRING(_T("SYSLOGREPORTING")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + pModeInfo->mbLogToSyslog = true; + else + pModeInfo->mbLogToSyslog = false; + } + else + pModeInfo->mbLogToSyslog = false; + + // Crossing file systems + if(cf.Lookup(TSTRING(_T("CROSSFILESYSTEMS")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + pModeInfo->mbCrossFileSystems = true; + else + pModeInfo->mbCrossFileSystems = false; + } + + // + // turn all of the file names into full paths (they're relative to the exe dir) + // + TSTRING fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mPolFile, cSystemInfo::GetExeDir() )) + pModeInfo->mPolFile = fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mDbFile, cSystemInfo::GetExeDir() )) + pModeInfo->mDbFile = fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mSiteKeyFile, cSystemInfo::GetExeDir() )) + pModeInfo->mSiteKeyFile = fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mLocalKeyFile, cSystemInfo::GetExeDir() )) + pModeInfo->mLocalKeyFile = fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mReportFile, cSystemInfo::GetExeDir() )) + pModeInfo->mReportFile = fullPath; +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutCmdLineInfo -- fills out info common to all modes that appears on the +// command line. +/////////////////////////////////////////////////////////////////////////////// +static void FillOutCmdLineInfo(cTWModeCommon* pModeInfo, const cCmdLineParser& cmdLine) +{ + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::VERBOSE: + pModeInfo->mVerbosity = 2; + break; + case cTWCmdLine::SILENT: + pModeInfo->mVerbosity = 0; + break; + case cTWCmdLine::POL_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mPolFile = iter.ParamAt(0); + break; + case cTWCmdLine::SITE_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mSiteKeyFile = iter.ParamAt(0); + break; + case cTWCmdLine::LOCAL_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mLocalKeyFile = iter.ParamAt(0); + break; + case cTWCmdLine::DB_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mDbFile = iter.ParamAt(0); + break; + case cTWCmdLine::REPORT_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mReportFile = iter.ParamAt(0); + break; + case cTWCmdLine::LOCAL_PASSPHRASE: + { + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mLocalPassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + pModeInfo->mLocalProvided = true; + } + break; +/* case cTWCmdLine::NO_BACKUP: + pModeInfo->mbBackup = false; + break; +*/ } + } + + // + // turn all of the file names into full paths for nice presentation to the user. + // + TSTRING fullPath; + if(iFSServices::GetInstance()->FullPath(fullPath, pModeInfo->mPolFile)) + pModeInfo->mPolFile = fullPath; + if(iFSServices::GetInstance()->FullPath(fullPath, pModeInfo->mSiteKeyFile)) + pModeInfo->mSiteKeyFile = fullPath; + if(iFSServices::GetInstance()->FullPath(fullPath, pModeInfo->mLocalKeyFile)) + pModeInfo->mLocalKeyFile = fullPath; + if(iFSServices::GetInstance()->FullPath(fullPath, pModeInfo->mDbFile)) + pModeInfo->mDbFile = fullPath; + if(iFSServices::GetInstance()->FullPath(fullPath, pModeInfo->mReportFile)) + pModeInfo->mReportFile = fullPath; + + + // use the verbosity information + ASSERT((pModeInfo->mVerbosity >= 0) && (pModeInfo->mVerbosity < 3)); + iUserNotify::GetInstance()->SetVerboseLevel(pModeInfo->mVerbosity); + + // if a passphrase was passed on the command line, then late prompting should + // be set to false so that wrong passwords are detected immediately + if( pModeInfo->mLocalProvided && pModeInfo->mbLatePassphrase ) + { + // TODO -- I don't know if we should display this or not -- mdb + //iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString( cTripwire, tripwire::STR_NOTIFY_CHANGE_PROMPT_TIME).c_str() ); + pModeInfo->mbLatePassphrase = false; + } +} + +//############################################################################# +// cTWModeDbInit +//############################################################################# +class cTWModeDbInit_i : public cTWModeCommon +{ +public: + bool mbEncryptDb; + + // ctor can set up some default values + cTWModeDbInit_i() : cTWModeCommon(), mbEncryptDb(true) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeDbInit::cTWModeDbInit() +{ + mpData = new cTWModeDbInit_i; +} + +cTWModeDbInit::~cTWModeDbInit() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeDbInit::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_INIT, TSTRING(_T("")), TSTRING(_T("init")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::NO_ENCRYPT, TSTRING(_T("e")), TSTRING(_T("no-encryption")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_NONE); + + // mutual exclusion... + cmdLine.AddMutEx(cTWCmdLine::NO_ENCRYPT, cTWCmdLine::LOCAL_PASSPHRASE); + cmdLine.AddMutEx(cTWCmdLine::NO_ENCRYPT, cTWCmdLine::LOCAL_KEY_FILE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeDbInit::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + // now do the stuff specific to this mode... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::NO_ENCRYPT: + mpData->mbEncryptDb = false; + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * site key file + // * policy file + // * db file + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), cTW, tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mSiteKeyFile.empty()), cTW, tw::STR_ERR_MISSING_SITE_KEY); + TEST_INIT_REQUIREMENT((! mpData->mPolFile.empty()), cTW, tw::STR_ERR_MISSING_POLICY); + TEST_INIT_REQUIREMENT((! mpData->mDbFile.empty()), cTW, tw::STR_ERR_MISSING_DB); + + + // make sure that the config file and site key file are in sync... + // + if (cTWUtil::VerifyCfgSiteKey( mstrConfigFile, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + + #if IS_UNIX + // Set the cross file systems flag appropriately. + cFSDataSourceIter::SetFileSystemCrossing(mpData->mbCrossFileSystems); + #endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeDbInit::Execute(cErrorQueue* pQueue) +{ + cFCODatabaseFile dbFile; + cFCODatabaseFile::iterator dbIter( dbFile ); + + dbFile.SetFileName( mpData->mDbFile ); + try + { + // don't go any further if we won't be able to write to the db file... + cFileUtil::TestFileWritable(mpData->mDbFile); + + // open the keyfile for early passphrase... + cKeyFile keyfile; + const cElGamalSigPrivateKey* pPrivateKey = 0; + if(mpData->mbEncryptDb) + { + cTWUtil::OpenKeyFile(keyfile, mpData->mLocalKeyFile); + // open the private key for "early passphrase" + if(! mpData->mbLatePassphrase) + pPrivateKey = cTWUtil::CreatePrivateKey(keyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + + //Parse the policy file + cGenreSpecListVector genreSpecList; + cTWCmdLineUtil::ParsePolicyFile(genreSpecList, mpData->mPolFile, mpData->mSiteKeyFile, pQueue); + + #ifdef TW_PROFILE + cWin32TaskTimer timer("cTripwire::GenerateDatabase"); + timer.Start(); + #endif + + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_GENERATING_DB ).c_str() ); + + uint32 gdbFlags = 0; + gdbFlags |= ( mpData->mbResetAccessTime ? cGenerateDb::FLAG_ERASE_FOOTPRINTS_GD : 0 ); + + // loop through the genres + cGenreSpecListVector::iterator genreIter; + for (genreIter = genreSpecList.begin(); genreIter != genreSpecList.end(); ++genreIter) + { + // make this genre the current genre. + // + cGenreSwitcher::GetInstance()->SelectGenre( genreIter->GetGenre() ); + + // notify the user + // + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString( cTripwire, tripwire::STR_PROCESSING_GENRE ).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( cGenreSwitcher::GetInstance()->CurrentGenre(), true ) ); + + // add an entry to the database for each genre we are parsing + dbFile.AddGenre( genreIter->GetGenre(), &dbIter ); + + // copy the spec list to the database... + dbIter.GetSpecList() = genreIter->GetSpecList(); + + // generate the database... + // TODO -- turn pQueue into an error bucket + cGenerateDb::Execute( dbIter.GetSpecList(), dbIter.GetDb(), dbIter.GetGenreHeader().GetPropDisplayer(), pQueue, gdbFlags ); + } + + cFCODatabaseUtil::CalculateHeader( + dbFile.GetHeader(), + mpData->mPolFile, + mstrConfigFile, + mpData->mDbFile, + mstrCmdLine, + cSystemInfo::GetExeStartTime(), + 0 + ); + + #ifdef TW_PROFILE + timer.Stop(); + #endif + + // write the db to disk... + if(mpData->mbEncryptDb) + { + // open the key file for late passphrase + if(! pPrivateKey) + { + ASSERT(mpData->mbLatePassphrase); + pPrivateKey = cTWUtil::CreatePrivateKey(keyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + + // backup the file we are about to overwrite + cFileUtil::BackupFile(mpData->mDbFile); + + cTWUtil::WriteDatabase(mpData->mDbFile.c_str(), dbFile, true, pPrivateKey); + keyfile.ReleasePrivateKey(); + } + else + { + cFileUtil::BackupFile(mpData->mDbFile); // backup the file we are about to overwrite + + cTWUtil::WriteDatabase(mpData->mDbFile.c_str(), dbFile, false, NULL); // false means no encryption + } + } + catch(eError& e) + { + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_INIT_FAIL_MSG ); + msg.append(cErrorTable::GetInstance()->Get( e.GetID() )); + + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_ERROR, msg.c_str()); + } + + cTWUtil::PrintErrorMsg(e); + return 8; + } + + // everything went ok; return 0 + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_INIT_SUCCESS ).c_str() ); + + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_INIT_MSG ) + mpData->mDbFile; + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_SUCCESS, msg.c_str()); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWModeDbInit::GetModeUsage( void ) +{ + return ( TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_INIT ) ); +} + +//############################################################################# +// cTWModeIC +//############################################################################# +class cTWModeIC_i : public cTWModeCommon +{ +public: + bool mbUpdate; // launch the editor after integrity checking is done + bool mbPrintToStdout; // print a text version of the report to stdout? + bool mbEmail; // email the report to the appropriate parties? + TSTRING mIgnoreProps; // symbols of properties to ignore + bool mbEncryptReport; // should the report be encrypted? + int mSeverityLevel; // only policy rules greater than or equal to the specified level will be checked. + bool mbTrimBySeverity; // do we use mSeverityLevel to trim the spec list? + TSTRING mSeverityName; // gets mapped to number, then treated like mSeverityLevel + TSTRING mRuleName; // only the named rule will be checked + TSTRING mGenreName; // if not empty, specifies the genre to check + bool mbAnal; // are we in anal mode? (only valid with mbUpdate == true) + +#ifdef GMMS + bool mbGmms; // Send violation reports via gmms? + TSTRING mGmmsProg; // full path to gmms executable + TSTRING mGmmsOptions; // additional options for gmms command line + int mGmmsVerbosity; // level 1 or 2 verbosity? +#endif + + //TSTRING mCmdLine; // entire command line + std::vector mFilesToCheck; + + // ctor can set up some default values + cTWModeIC_i() : cTWModeCommon(), mbUpdate(false), mbPrintToStdout(true), mbEmail(false), mbEncryptReport(false), + mSeverityLevel(-1), mbTrimBySeverity(false), mbAnal(false) +#ifdef GMMS + , mbGmms(false), mGmmsVerbosity(2) +#endif + {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeIC::cTWModeIC() +{ + mpData = new cTWModeIC_i; +} + +cTWModeIC::~cTWModeIC() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeIC::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_CHECK, TSTRING(_T("")), TSTRING(_T("check")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::INTER_UPDATE, TSTRING(_T("I")), TSTRING(_T("interactive")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::EDITOR, TSTRING(_T("V")), TSTRING(_T("visual")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::NO_TTY, TSTRING(_T("n")), TSTRING(_T("no-tty-output")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::MAIL_REPORT, TSTRING(_T("M")), TSTRING(_T("email-report")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::IGNORE_PROP, TSTRING(_T("i")), TSTRING(_T("ignore")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::ENCRYPT_REPORT, TSTRING(_T("E")), TSTRING(_T("signed-report")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::SEVERITY_LEVEL, TSTRING(_T("l")), TSTRING(_T("severity")), cCmdLineParser::PARAM_ONE); + //cmdLine.AddArg(cTWCmdLine::SEVERITY_NAME, TSTRING(_T("V")), TSTRING(_T("severityname")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::RULE_NAME, TSTRING(_T("R")), TSTRING(_T("rule-name")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::GENRE_NAME, TSTRING(_T("x")), TSTRING(_T("section")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); + + // multiple levels of reporting + cmdLine.AddArg(cTWCmdLine::REPORTLEVEL, TSTRING(_T("t")), TSTRING(_T("email-report-level")), cCmdLineParser::PARAM_ONE); + +#ifdef GMMS + // gmms command line options + cmdLine.AddArg(cTWCmdLine::USE_GMMS, TSTRING(_T("g")), TSTRING(_T("gmms")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::GMMS_VERBOSITY, TSTRING(_T("b")), TSTRING(_T("gmms-verbosity")), cCmdLineParser::PARAM_ONE); +#endif + + // mutual exclusion... + // you can't specify any of these 3 things together... + cmdLine.AddMutEx(cTWCmdLine::SEVERITY_LEVEL, cTWCmdLine::RULE_NAME); + cmdLine.AddDependency( cTWCmdLine::REPORTLEVEL, cTWCmdLine::MAIL_REPORT ); + // Report error if the user has specified an editor and we're not in interactive update + // mode: This needs to happen here, so we don't nail someone for having the editor + // specified in the config. file. We should only be this picky if both parameters are + // passed on the command line. + cmdLine.AddDependency( cTWCmdLine::EDITOR, cTWCmdLine::INTER_UPDATE ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeIC::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // We will use this to access the parsed cmdLine. + cCmdLineIter iter(cmdLine); + +#ifdef GMMS + + // Get path to gmms executable from config file + TSTRING str; + if(cf.Lookup(TSTRING(_T("GMMS")), str)) + { + // Path was specified in the configuration file + mpData->mGmmsProg = str; + } + else + { + // Path was not specified in the configuration file, try environment variable + const TCHAR *gmmsDeploy = _tgetenv(_T("GEOPLEX_DEPLOY")); + if (gmmsDeploy) + mpData->mGmmsProg = TSTRING(gmmsDeploy) + _T("/bin/gmms"); // Assign by env.var. + else + mpData->mGmmsProg = _T("/home/geoplex/bin/gmms"); // No env.var., Take a wild guess. + } + + // Get any additional command line options for running gmms from config file + if(cf.Lookup(TSTRING(_T("GMMSOPTIONS")), str)) + mpData->mGmmsOptions = str; + + bool bGmmsSpecified=false, bGmmsVerbositySpecified=false; + +#endif + + // First, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // Now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + + // now do the stuff specific to this mode.. + + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::INTER_UPDATE: + mpData->mbUpdate = true; + break; + case cTWCmdLine::EDITOR: + ASSERT(iter.NumParams() > 0); + mpData->mEditor = iter.ParamAt(0); + break; + case cTWCmdLine::NO_TTY: + mpData->mbPrintToStdout = false; + break; + case cTWCmdLine::MAIL_REPORT: + mpData->mbEmail = true; + break; + case cTWCmdLine::IGNORE_PROP: + ASSERT(iter.NumParams() > 0); + mpData->mIgnoreProps = iter.ParamAt(0); + break; + case cTWCmdLine::ENCRYPT_REPORT: + mpData->mbEncryptReport = true; + break; + case cTWCmdLine::SEVERITY_LEVEL: + ASSERT(iter.NumParams() > 0); + if (_istdigit(iter.ParamAt(0).c_str()[0])) + { + // interpret severity value + int iSev; + cSeverityLimits sl; + if( ! sl.InterpretInt( iter.ParamAt(0), &iSev ) ) + throw eICBadSevVal( iter.ParamAt(0) ); + + mpData->mSeverityLevel = iSev; + mpData->mbTrimBySeverity = true; + } + else + { + mpData->mSeverityName = iter.ParamAt(0); + } + break; + case cTWCmdLine::REPORTLEVEL: + { + if ( iter.ParamAt(0) == _T("0")) + mpData->mEmailReportLevel = cTextReportViewer::SINGLE_LINE; + else if( iter.ParamAt(0) == _T("1") ) + mpData->mEmailReportLevel = cTextReportViewer::PARSEABLE; + else if( iter.ParamAt(0) == _T("2") ) + mpData->mEmailReportLevel = cTextReportViewer::SUMMARY_ONLY; + else if( iter.ParamAt(0) == _T("3") ) + mpData->mEmailReportLevel = cTextReportViewer::CONCISE_REPORT; + else if( iter.ParamAt(0) == _T("4") ) + mpData->mEmailReportLevel = cTextReportViewer::FULL_REPORT; + else + { + // They specified an illegal level, error. + TSTRING errStr = _T("Invalid Level: "); + errStr += iter.ParamAt(0); + throw eTWInvalidReportLevel( errStr ); + } + } + //done with report-level stuff. + break; + case cTWCmdLine::RULE_NAME: + ASSERT(iter.NumParams() > 0); + mpData->mRuleName = iter.ParamAt(0); + break; + case cTWCmdLine::GENRE_NAME: + ASSERT(iter.NumParams() > 0); + mpData->mGenreName = iter.ParamAt(0); + break; + case cTWCmdLine::PARAMS: + { + // pack all of these onto the files to check list... + mpData->mFilesToCheck.clear(); + for(int i=0; i < iter.NumParams(); i++) + { + mpData->mFilesToCheck.push_back(iter.ParamAt(i)); + } + } +#ifdef GMMS + case cTWCmdLine::USE_GMMS: + mpData->mbGmms = true; + bGmmsSpecified = true; + break; + case cTWCmdLine::GMMS_VERBOSITY: + { + const TCHAR* psz = iter.ParamAt(0).c_str(); + if ( psz != 0 ) + while ( _istdigit( *psz ) ) ++psz; + + /// NOTE:RAD -- Come on man! There isn't even a pStr!!! + // if ( !cStringUtil::StringIsInteger( pStr ) ) + if ( *psz != 0x00 ) + { + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_BAD_GMMS_VERBOSITY ) << std::endl; + return false; + } + else + { + mpData->mGmmsVerbosity = _ttoi(iter.ParamAt(0).c_str()); + if (mpData->mGmmsVerbosity < 1 || mpData->mGmmsVerbosity > 2) { + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_BAD_GMMS_VERBOSITY ) << std::endl; + return false; + } + bGmmsVerbositySpecified = true; + } + break; + } +#endif + default: + // should I do anything, or just ignore this? + ; + } + } + + + // if an editor is not provided in cfg or on cmdline, try to get it from environment + if( mpData->mbUpdate && mpData->mEditor.empty() ) + util_GetEditor( mpData->mEditor ); + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * site key file + // * policy file + // * db file + // * report file + // * editor (if interactive is specified) + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), cTW, tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mSiteKeyFile.empty()), cTW, tw::STR_ERR_MISSING_SITE_KEY); + TEST_INIT_REQUIREMENT((! mpData->mPolFile.empty()), cTW, tw::STR_ERR_MISSING_POLICY); + TEST_INIT_REQUIREMENT((! mpData->mDbFile.empty()), cTW, tw::STR_ERR_MISSING_DB); + TEST_INIT_REQUIREMENT((! mpData->mReportFile.empty()), cTW, tw::STR_ERR_MISSING_REPORT); + TEST_INIT_REQUIREMENT((! (mpData->mEditor.empty() && mpData->mbUpdate)),cTW, tw::STR_ERR_MISSING_EDITOR); + +#ifdef GMMS + if (bGmmsSpecified==false && bGmmsVerbositySpecified==true) + { + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_GMMS_VERBOSITY_ONLY ) << std::endl; + return false; + } +#endif + + /////////////////////////////////////////// + // do some email-related verifications + /////////////////////////////////////////// + if(mpData->mbEmail) + { + // make sure that email reporting and a file list were both not specified... + TEST_INIT_REQUIREMENT( mpData->mFilesToCheck.empty(), cTripwire, tripwire::STR_ERR_IC_EMAIL_AND_FILES ); + + // make sure that we have a valid mail method + TEST_INIT_REQUIREMENT( ( cMailMessage::NO_METHOD != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_NO_MAIL_METHOD ); + TEST_INIT_REQUIREMENT( ( cMailMessage::INVALID_METHOD != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_INVALID_MAIL_METHOD ); + + // error if method is SENDMAIL and no MAILPROGRAM + TEST_INIT_REQUIREMENT( ( cMailMessage::MAIL_BY_PIPE != mpData->mMailMethod || !mpData->mMailProgram.empty()), + cTripwire, tripwire::STR_ERR_MISSING_MAILPROGRAM ); + +#if !SUPPORTS_MAPI + TEST_INIT_REQUIREMENT( ( cMailMessage::MAIL_BY_MAPI != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_MAPI_NOT_SUPPORTED ); +#endif + } + + // make sure that the config file and site key file are in sync... + // + if (cTWUtil::VerifyCfgSiteKey( mstrConfigFile, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + + #if IS_UNIX + // Set the cross file systems flag appropriately. + cFSDataSourceIter::SetFileSystemCrossing(mpData->mbCrossFileSystems); + #endif + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeIC::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWModeIC::Execute"); + + cFCODatabaseFile dbFile; + cFCODatabaseFile::iterator dbIter( dbFile ); + cFCOReport report; + cFCOReportHeader reportHeader; + bool bEncrypted, bCheckMade = false, bEmailError = false; + try + { + + // don't go any further if we won't be able to write the report to disk... + cFileUtil::TestFileWritable(mpData->mReportFile); + + // open the database; note that ReadDatabase will set bEncrypted and open the + // key file if necessary + cKeyFile localKeyfile; + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), dbFile, localKeyfile.GetPublicKey(), bEncrypted); + + // + // give a warning if the user that created the database is not the same as the user running right now... + // + TSTRING userName; + if( iFSServices::GetInstance()->GetCurrentUserName( userName ) ) + { + if( dbFile.GetHeader().GetCreator().compare( userName.c_str() ) != 0 ) + { + // TODO -- move these strings to the string table + TOSTRINGSTREAM str; + str << TSS_GetString( cTripwire, tripwire::STR_ERR2_DIFFERENT_USERS1) << dbFile.GetHeader().GetCreator() + << TSS_GetString( cTripwire, tripwire::STR_ERR2_DIFFERENT_USERS2) << userName << std::ends; + cTWUtil::PrintErrorMsg( eICDifferentUsers( str.str(), eError::NON_FATAL ) ); + } + } + + // give a stern warning if the database is not encrypted + if(! bEncrypted && iUserNotify::GetInstance()->GetVerboseLevel() > iUserNotify::V_SILENT) + { + cTWUtil::PrintErrorMsg(eTWDbNotEncrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + + if( (!bEncrypted) && (mpData->mLocalProvided) && (!mpData->mbEncryptReport) ) + { + //Issue a warning if a passphrase has been supplied, and the database is NOT encrypted. + cTWUtil::PrintErrorMsg( eTWPassForUnencryptedDb( _T(""), eError::NON_FATAL)); + } + + + // get the password here if they are saving an encrypted report + const cElGamalSigPrivateKey* pPrivateKey = 0; + if(mpData->mbEncryptReport) + { + // if the key file isn't open (ie -- the report wasn't encrypted) then we need to + // open it now... + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + + // open the private key for "early passphrase" + if(! mpData->mbLatePassphrase) + { + // OK, here is the deal: if the user specified a password on the command line + // and we are going to do an interactive update after the IC and both the report + // and db are encrypted, then we need to save the passphrase so it doesn't get + // scrambled by CreatePrivateKey + if(mpData->mLocalProvided && mpData->mbUpdate && bEncrypted) + { + wc16_string passPhrase = mpData->mLocalPassphrase.c_str(); + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, passPhrase.c_str(), cTWUtil::KEY_LOCAL); + } + else + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + } + + // either integrity check using the policy file or a list of files + if(mpData->mFilesToCheck.size() != 0) + { + // we are checking files... + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_IC_FILES).c_str() ); + //// + // tell the user we are ignoring severity level and rule name, if they specified them... + // + if( ! mpData->mRuleName.empty() ) + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString( cTripwire, tripwire::STR_IC_IGNORING_RULE_NAME).c_str() ); + if( mpData->mbTrimBySeverity ) + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString( cTripwire, tripwire::STR_IC_IGNORING_SEV_NUM).c_str() ); + if( ! mpData->mSeverityName.empty() ) + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString( cTripwire, tripwire::STR_IC_IGNORING_SEV_NAME).c_str() ); + if( ! mpData->mGenreName.empty() ) + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString( cTripwire, tripwire::STR_IC_IGNORING_GENRE_NAME).c_str() ); + // + //// + + //********************************** + // new, experimental stuff.. trying out new command line interface + // + cTWUtil::GenreObjList listOut; + cTWUtil::ParseObjectList( listOut, mpData->mFilesToCheck ); + // + // now, we will iterate over the list, performing an integrity check for each genre + // + for( cTWUtil::GenreObjList::iterator genreIter = listOut.begin(); genreIter != listOut.end(); genreIter++ ) + { + dbIter.SeekToGenre( genreIter->first ); + if( ! dbIter.Done() ) + { + cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre)dbIter.GetGenre() ); + std::auto_ptr pParseUtil (iTWFactory::GetInstance()->CreateParserGenreUtil()); + // + // I have to turn this into a list of cFCONames + // + std::list fcoNames; + for(cTWUtil::ObjList::iterator it = genreIter->second.begin(); it != genreIter->second.end(); it++) + { + // if this is not an absolute path, warn and continue... + // + try + { + fcoNames.push_back( cTWUtil::ParseObjectName( *it ) ); + } + catch( eError& e ) + { + e.SetFatality( false ); + pQueue->AddError( e ); + report.GetErrorQueue()->AddError( e ); + } + } + // TODO -- emit "processing XXX" + cIntegrityCheck ic( (cGenre::Genre)genreIter->first, dbIter.GetSpecList(), dbIter.GetDb(), report, pQueue ); + + uint32 icFlags = 0; + icFlags |= ( mpData->mfLooseDirs ? cIntegrityCheck::FLAG_LOOSE_DIR : 0 ); + icFlags |= ( mpData->mbResetAccessTime ? cIntegrityCheck::FLAG_ERASE_FOOTPRINTS_IC : 0 ); + + ic.ExecuteOnObjectList( fcoNames, icFlags ); + + // put all info into report + cFCOReportGenreIter rgi( report ); + rgi.SeekToGenre( (cGenre::Genre) genreIter->first ); + rgi.GetGenreHeader().SetPropDisplayer( iTWFactory::GetInstance()->CreatePropDisplayer() ); + rgi.GetGenreHeader().GetPropDisplayer()->Merge( dbIter.GetGenreHeader().GetPropDisplayer() ); + rgi.GetGenreHeader().SetObjectsScanned( ic.ObjectsScanned() ); + } + else + { + //TODO -- what is the right thing to do here? + // error and continue or exit? + // + eTWDbDoesntHaveGenre e( cGenreSwitcher::GetInstance()->GenreToString( (cGenre::Genre)genreIter->first, true ) ); + e.SetFatality( false ); + cTWUtil::PrintErrorMsg( e ); + } + } + // + //********************************** + } + else + { + // we are checking a subset of the policy file + + // parse the policy file + cGenreSpecListVector genreSpecList; + cTWCmdLineUtil::ParsePolicyFile(genreSpecList, mpData->mPolFile, mpData->mSiteKeyFile, pQueue); + + // + // make sure the parsed policy is equivelant to the one in the database... + // TODO -- should this go in the report? should I make a report or just bail? I guess + // that for now, I will bail. (it throws an exception on failure + // + cTWCmdLineUtil::VerifyPolicy( genreSpecList, dbFile ) ; + + // + // if they are only checking one genre, figure out which one it is ... + // + cGenre::Genre genreToCheck = cGenre::GENRE_INVALID; + if( ! mpData->mGenreName.empty() ) + { + genreToCheck = cGenreSwitcher::GetInstance()->StringToGenre( mpData->mGenreName.c_str() ); + if( genreToCheck == cGenre::GENRE_INVALID ) + { + throw eICUnknownGenre( mpData->mGenreName ); + } + if( ! cGenreSwitcher::GetInstance()->IsGenreAppropriate( genreToCheck ) ) + { + throw eICInappropriateGenre( mpData->mGenreName ); + } + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString( cTripwire, tripwire::STR_CHECKING_GENRE).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( genreToCheck ) ); + } + + + // iterate over the genres... + // + cGenreSpecListVector::iterator genreIter; + for (genreIter = genreSpecList.begin(); genreIter != genreSpecList.end(); ++genreIter) + { + // if they are only checking one genre and it is not this one, then + // skip everything else... + // + if( (genreToCheck != cGenre::GENRE_INVALID) && (genreToCheck != genreIter->GetGenre()) ) + continue; + + // make this genre the current genre. + // + cGenreSwitcher::GetInstance()->SelectGenre( genreIter->GetGenre() ); + // + // seek the database iter to this genre... + // + dbIter.SeekToGenre( genreIter->GetGenre() ); + if( dbIter.Done() ) + { + // TODO -- what is the right thing to do here? throw or warn and continue? + // I think that I should add it to the report's error queue and spit it to + // stderr and continue + // + TCERR << _T("Genre ") << cGenreSwitcher::GetInstance()->GenreToString( genreIter->GetGenre() ) + << _T(" not in database; skipping.") << std::endl; + continue; + } + // message to the user... + // + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString( cTripwire, tripwire::STR_PROCESSING_GENRE ).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( cGenreSwitcher::GetInstance()->CurrentGenre(), true ) ); + + cFCOSpecList specList = genreIter->GetSpecList(); + + // trim ignored properties from the specs... + if(! mpData->mIgnoreProps.empty()) + cTWCmdLineUtil::TrimPropsFromSpecs(specList, mpData->mIgnoreProps); + + // trim ignored rule names from the specs... + if(! mpData->mRuleName.empty()) + cTWCmdLineUtil::TrimSpecsByName(specList, mpData->mRuleName); + + // trim spec list based on severity + if(mpData->mbTrimBySeverity) + cTWCmdLineUtil::TrimSpecsBySeverity(specList, mpData->mSeverityLevel); + + // trim specs by severity name + if(! mpData->mSeverityName.empty()) + cTWCmdLineUtil::TrimSpecsBySeverityName(specList, mpData->mSeverityName); + + // + // only do the integrity check if there is something to check! + // + if( ! specList.IsEmpty() ) + { + bCheckMade = true; //we've checked at least one rule. + + // do the integrity check... + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_INTEGRITY_CHECK).c_str()); + +#ifdef TW_PROFILE + cWin32TaskTimer timer("cTripwire::IntegrityCheck"); + timer.Start(); +#endif + cIntegrityCheck ic( (cGenre::Genre)dbIter.GetGenre(), specList, dbIter.GetDb(), report, pQueue ); + + uint32 icFlags = 0; + icFlags |= ( mpData->mfLooseDirs ? cIntegrityCheck::FLAG_LOOSE_DIR : 0 ); + icFlags |= ( mpData->mbResetAccessTime ? cIntegrityCheck::FLAG_ERASE_FOOTPRINTS_IC : 0 ); + + ic.Execute( icFlags ); + + // put all display info into report + cFCOReportGenreIter rgi( report ); + rgi.SeekToGenre( (cGenre::Genre) dbIter.GetGenre() ); + rgi.GetGenreHeader().SetPropDisplayer( iTWFactory::GetInstance()->CreatePropDisplayer() ); + rgi.GetGenreHeader().GetPropDisplayer()->Merge( dbIter.GetGenreHeader().GetPropDisplayer() ); + rgi.GetGenreHeader().SetObjectsScanned( ic.ObjectsScanned() ); + +#ifdef TW_PROFILE + timer.Stop(); +#endif + } + else + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString( cTripwire, tripwire::STR_ERR_IC_NO_SPECS_LEFT).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( genreIter->GetGenre(), true ) ); + + } + } + } + + // save out the report... + cFCOReportUtil::CalculateHeaderInfo( + reportHeader, + mpData->mPolFile, + mstrConfigFile, + mpData->mDbFile, + mstrCmdLine, + cSystemInfo::GetExeStartTime(), + dbFile.GetHeader().GetLastDBUpdateTime() + ); + + cFCOReportUtil::FinalizeReport( report ); + +#ifdef GMMS + // gmms reporting? + if (mpData->mbGmms) + { + try + { + cTWCmdLineUtil::GmmsReport(reportHeader, report, mpData->mGmmsProg, mpData->mGmmsOptions, mpData->mGmmsVerbosity); + } + catch(eGmmsError& e) + { + cTWUtil::PrintErrorMsg(e); + // Do not return. Gmms errors are not fatal. + } + } +#endif + + // email the report if that is desired... + if(mpData->mbEmail) + { + bEmailError = cTWCmdLineUtil::EmailReport(reportHeader, report, mpData) == 0; + + // We should notify them that no email was sent should the following condition + // apply. + if( !bCheckMade ) + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString( cTripwire, tripwire::STR_IC_NOEMAIL_SENT).c_str(), + _T("") ); + } + } + + // write the report to disk... + if(mpData->mbEncryptReport) + { + // get the private key for "late passphrase" + if(! pPrivateKey) + { + ASSERT(mpData->mbLatePassphrase); + // OK, here is the deal: if the user specified a password on the command line + // and we are going to do an interactive update after the IC and both the report + // and db are encrypted, then we need to save the passphrase so it doesn't get + // scrambled by CreatePrivateKey + if(mpData->mLocalProvided && mpData->mbUpdate && bEncrypted) + { + wc16_string passPhrase = mpData->mLocalPassphrase.c_str(); + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, passPhrase.c_str(), cTWUtil::KEY_LOCAL); + } + else + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + + // backup the file we are about to overwrite + cFileUtil::BackupFile(mpData->mReportFile); + + // write the report + cTWUtil::WriteReport(mpData->mReportFile.c_str(), reportHeader, report, true, pPrivateKey); + localKeyfile.ReleasePrivateKey(); + } + else + { + cFileUtil::BackupFile(mpData->mReportFile); // backup the file we are about to overwrite + cTWUtil::WriteReport(mpData->mReportFile.c_str(), reportHeader, report, false, NULL); // false means no encryption + } + + // print a text version of the report to stdout... + if(mpData->mbPrintToStdout) + { + // print a couple of new lines so that the report isn't butted up against the rest of the output. + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, _T("\n\n")); + cTextReportViewer trv( reportHeader, report ); + trv.PrintTextReport( _T("-"), cTextReportViewer::SUMMARY_ONLY ); + } + + } + catch(eError& e) + { + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IC_FAIL_MSG ); + msg.append(cErrorTable::GetInstance()->Get( e.GetID() )); + + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_ERROR, msg.c_str()); + } + + cTWUtil::PrintErrorMsg(e); + return 8; + //TODO -- send a sad email here if mbEmail == true + } + + // tell the user the report was saved + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_IC_SUCCESS).c_str()); + + if (mpData->mbLogToSyslog) + { + cTextReportViewer trv( reportHeader, report ); + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IC_MSG ); + msg.append(mpData->mDbFile); + msg.append(_T(" ")); + msg.append(trv.SingleLineReport()); + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_SUCCESS, msg.c_str()); + } + + // go directly into interactive update if that is what they want... + // + if(mpData->mbUpdate) + { + cTWModeDbUpdate dbUpdate; + dbUpdate.Init(mpData, &dbFile, &reportHeader, &report, bEncrypted); + int ret = dbUpdate.Execute(pQueue); + + if (ret != 0) + return ret; + } + + // the return level is based on the type of violations that were found: + // 1 = added files + // 2 = removed files + // 4 = changed files + // 8 = ERROR_IC = Execution Error + if(bEmailError) + return (ERROR_IC | cTWCmdLineUtil::GetICReturnValue(report)); + else + return cTWCmdLineUtil::GetICReturnValue(report); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWModeIC::GetModeUsage( void ) +{ + return ( TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_CHECK ) ); +} + +//############################################################################# +// cTWModeDbUpdate +//############################################################################# +class cTWModeDbUpdate_i : public cTWModeCommon +{ +public: + bool mbInteractive; // don't do interactive update; just integrate the report file + bool mbAnal; // are we in anal mode? + //std::string mSitePassphrase; // pass phrase for site key + //bool mSiteProvided; + + // these members are only used when this mode is entered after integrity checking. + // they are set to variables that are on cTWModeIC's stack, so they should _not_ be deleted. + // if they are non-null when Execute() is called, they should be used as the db and report. + bool mbEncryptDb; + cFCOReport* mpReport; + cFCODatabaseFile* mpDbFile; + cFCOReportHeader* mpReportHeader; + + // ctor can set up some default values + cTWModeDbUpdate_i() : cTWModeCommon(), mbInteractive(true), mbAnal(true), /*mSiteProvided(false),*/ mpReport(0), mpDbFile(0), mpReportHeader(0) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeDbUpdate::cTWModeDbUpdate() +{ + mpData = new cTWModeDbUpdate_i; +} + + + +cTWModeDbUpdate::~cTWModeDbUpdate() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeDbUpdate::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_UPDATE_DB, TSTRING(_T("")), TSTRING(_T("update")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::ACCEPT_ALL, TSTRING(_T("a")), TSTRING(_T("accept-all")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::ANAL_LEVEL, TSTRING(_T("Z")), TSTRING(_T("secure-mode")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::EDITOR, TSTRING(_T("V")), TSTRING(_T("visual")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_NONE); + + // mutual exclusion... + cmdLine.AddMutEx(cTWCmdLine::ACCEPT_ALL, cTWCmdLine::EDITOR); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeDbUpdate::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + // now do the stuff specific to this mode... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::ACCEPT_ALL: + mpData->mbInteractive = false; + break; + case cTWCmdLine::ANAL_LEVEL: + ASSERT(iter.NumParams() > 0); + if(iter.ParamAt(0).compare(_T("high")) == 0) + mpData->mbAnal = true; + else if(iter.ParamAt(0).compare(_T("low")) == 0) + mpData->mbAnal = false; + else + { + // invalid parameter to anal switch... + // TODO -- print this to stderr; how do I display (1) the switch name + // and (2) the possible values? + // TODO -- move {high, low} somewhere else + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_BAD_PARAM) << _T(" : ") + << iter.ParamAt(0).c_str() << _T("; must be {high, low}") << std::endl; + return false; + } + break; + case cTWCmdLine::EDITOR: + ASSERT(iter.NumParams() > 0); + mpData->mEditor = iter.ParamAt(0); + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + // if an editor is not provided in cfg or on cmdline, try to get it from environment + if( mpData->mbInteractive && mpData->mEditor.empty() ) + util_GetEditor( mpData->mEditor ); + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * site key file + // * policy file + // * db file + // * report file + // * editor (if accept all is not specified) + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), cTW, tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mSiteKeyFile.empty()), cTW, tw::STR_ERR_MISSING_SITE_KEY); + TEST_INIT_REQUIREMENT((! mpData->mPolFile.empty()), cTW, tw::STR_ERR_MISSING_POLICY); + TEST_INIT_REQUIREMENT((! mpData->mDbFile.empty()), cTW, tw::STR_ERR_MISSING_DB); + TEST_INIT_REQUIREMENT((! mpData->mReportFile.empty()), cTW, tw::STR_ERR_MISSING_REPORT); + TEST_INIT_REQUIREMENT(((!mpData->mEditor.empty()) || (!mpData->mbInteractive)), cTW, tw::STR_ERR_MISSING_EDITOR); + + // make sure that the config file and site key file are in sync... + // + if (cTWUtil::VerifyCfgSiteKey( mstrConfigFile, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + + #if IS_UNIX + // Set the cross file systems flag appropriately. + cFSDataSourceIter::SetFileSystemCrossing(mpData->mbCrossFileSystems); + #endif + + return true; +} + +void cTWModeDbUpdate::Init(const cTWModeIC_i* pICData, cFCODatabaseFile* dbFile, cFCOReportHeader* prh, cFCOReport* pReport, bool bEncryptDb) +{ + mpData->mbInteractive = true; // always interactive + mpData->mbAnal = pICData->mbAnal; + //mpData->mbBackup = pICData->mbBackup; + mpData->mDbFile = pICData->mDbFile; + mpData->mLocalKeyFile = pICData->mLocalKeyFile; + mpData->mLocalPassphrase= pICData->mLocalPassphrase; + mpData->mLocalProvided = pICData->mLocalProvided; + mpData->mPolFile = pICData->mPolFile; + mpData->mReportFile = pICData->mReportFile; + mpData->mSiteKeyFile = pICData->mSiteKeyFile; + mpData->mVerbosity = pICData->mVerbosity; + mpData->mEditor = pICData->mEditor; + mpData->mbLatePassphrase= pICData->mbLatePassphrase; + + + mpData->mbEncryptDb = bEncryptDb; + mpData->mpDbFile = dbFile; + + if(pReport) + { + ASSERT(prh != 0); + mpData->mpReport = pReport; + mpData->mpReportHeader = prh; + } + else + { + mpData->mpReport = 0; + mpData->mpReportHeader = 0; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeDbUpdate::Execute(cErrorQueue* pQueue) +{ + try + { + // don't go any further if we won't be able to write to the db file... + cFileUtil::TestFileWritable(mpData->mDbFile); + + // open the database + cFCODatabaseFile dbFile; + cKeyFile localKeyfile; + bool bDbEncrypted, bReportEncrypted; + + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + + if(! mpData->mpDbFile) + { + // open the database; note that ReadDatabase will set bEncrypted and open the + // key file if necessary + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), dbFile, localKeyfile.GetPublicKey(), bDbEncrypted); + mpData->mpDbFile = &dbFile; + } + else + { + // we were passed the database; we should open the key file now if the db needs + // to be saved encrypted... + if(mpData->mbEncryptDb) + bDbEncrypted = true; + else + bDbEncrypted = false; + } + + if( (!bDbEncrypted) && (mpData->mLocalProvided) ) + { + //Issue a warning if a passphrase has been supplied, and the database is NOT encrypted. + cTWUtil::PrintErrorMsg( eTWPassForUnencryptedDb( _T(""), eError::NON_FATAL)); + } + + + // open the report... + cFCOReport report; + cFCOReportHeader reportHeader; + if(! mpData->mpReport) + { + cTWUtil::ReadReport(mpData->mReportFile.c_str(), reportHeader, report, localKeyfile.GetPublicKey(), false, bReportEncrypted); + mpData->mpReport = &report; + mpData->mpReportHeader = &reportHeader; + } + else + ASSERT(mpData->mpReportHeader != 0); + + // open the private key for "early passphrase" + // I don't think that early passphrase should apply to db update; there is no reason the user + // would want to enter the passphrase before editing the report .. mdb + // TODO: Well ok, can we remove this commented out code then? + const cElGamalSigPrivateKey* pPrivateKey = 0; + /* + if(bDbEncrypted && (! mpData->mbLatePassphrase)) + { + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0); + } + */ + + // have the user modify the report, if they want to + if(mpData->mbInteractive) + { + // put a try/catch here to allow ourselves to print a message + // saying the editor launch failed + try + { + cTextReportViewer trv( *mpData->mpReportHeader, *mpData->mpReport ); + trv.DisplayReportAndHaveUserUpdateIt( mpData->mEditor, cTextReportViewer::FULL_REPORT ); + } + catch(...) + { + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_UPDATE_ED_LAUNCH) << std::endl; + throw; + } + } + + // if the report is empty, there is no need to do the update... + if(! cTWCmdLineUtil::ReportContainsFCO(*mpData->mpReport)) + { + // tell them ... + iUserNotify::GetInstance()->Notify(1, TSS_GetString( cTripwire, tripwire::STR_REPORT_EMPTY).c_str()); + // keep those pesky ASSERTs from cKeyFile away! + if(pPrivateKey) + localKeyfile.ReleasePrivateKey(); + return 0; // is this the right return val? + } + + // give a stern warning if the database is not encrypted + if(! bDbEncrypted && iUserNotify::GetInstance()->GetVerboseLevel() > iUserNotify::V_SILENT) + { + // warn if the database is not encrytped + cTWUtil::PrintErrorMsg(eTWDbNotEncrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + + // iterate over all the genres in the report... + // + cFCOReportGenreIter genreIter( *mpData->mpReport ); + for( genreIter.SeekBegin(); ! genreIter.Done(); genreIter.Next() ) + { + cGenreSwitcher::GetInstance()->SelectGenre( genreIter.GetGenre() ); + // + // seek the db iter to the current genre... + // + cFCODatabaseFile::iterator dbIter( *mpData->mpDbFile ); + dbIter.SeekToGenre( genreIter.GetGenre() ); + if( dbIter.Done() ) + { + //TODO -- what is the right thing to do here? + // + ASSERT( false ); + throw eTWDbDoesntHaveGenre(); + } + // + // actually do the integrity check... + // + uint32 udFlags = 0; + udFlags |= ( mpData->mbResetAccessTime ? cUpdateDb::FLAG_ERASE_FOOTPRINTS_UD : 0 ); + + cUpdateDb update( dbIter.GetDb(), *mpData->mpReport, pQueue ); + if( (! update.Execute( udFlags )) && mpData->mbAnal ) + { + // we will not perform the update; simply exit. + TCOUT << TSS_GetString( cTripwire, tripwire::STR_DB_NOT_UPDATED) << std::endl; + return 8; + } + + // + // update the header info for the database... + // + // merge the prop displayers... + dbIter.GetGenreHeader().GetPropDisplayer()->Merge( genreIter.GetGenreHeader().GetPropDisplayer() ); + } + + // Update the header + // Note: We DO NOT call cFCODatabaseUtil::CalculateHeader() here. We only + // want to update these entries. + mpData->mpDbFile->GetHeader().SetCreator(cTWUtil::GetCurrentUser()); + mpData->mpDbFile->GetHeader().SetLastDBUpdateTime( cSystemInfo::GetExeStartTime() ); + + // + // write the db to disk... + // + if(bDbEncrypted) + { + // open the private key for "late prompting" + if(! pPrivateKey) + { + pPrivateKey = cTWUtil::CreatePrivateKey(localKeyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + + // backup the file we are about to overwrite + cFileUtil::BackupFile(mpData->mDbFile); + + cTWUtil::WriteDatabase(mpData->mDbFile.c_str(), *mpData->mpDbFile, true, pPrivateKey); + localKeyfile.ReleasePrivateKey(); + } + else + { + cFileUtil::BackupFile(mpData->mDbFile); // backup the file we are about to overwrite + cTWUtil::WriteDatabase(mpData->mDbFile.c_str(), *mpData->mpDbFile, false, NULL); // false means no encryption + } + } + catch(eError& e) + { + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_UP_FAIL_MSG ); + msg.append(cErrorTable::GetInstance()->Get( e.GetID() )); + + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_ERROR, msg.c_str()); + } + + cTWUtil::PrintErrorMsg(e); + return 8; + } + + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_UP_MSG ); + msg.append(mpData->mDbFile); + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_SUCCESS, msg.c_str()); + } + + // everything went ok; return 0 + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWModeDbUpdate::GetModeUsage( void ) +{ + return ( TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE ) ); +} + +//############################################################################# +// cTWModePolUpdate +//############################################################################# +class cTWModePolUpdate_i : public cTWModeCommon +{ +public: + TSTRING mTextPolFile; + wc16_string mSitePassphrase; + bool mSiteProvided; + bool mbAnal; + + // ctor can set up some default values + cTWModePolUpdate_i() : cTWModeCommon(), mSiteProvided(false), mbAnal(true) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModePolUpdate::cTWModePolUpdate() +{ + mpData = new cTWModePolUpdate_i; +} + +cTWModePolUpdate::~cTWModePolUpdate() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModePolUpdate::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_UPDATE_POL, TSTRING(_T("")), TSTRING(_T("update-policy")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::TEXT_POL_FILE, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::LOCAL_PASSPHRASE,TSTRING(_T("P")), TSTRING(_T("local-passphrase")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::SITE_PASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + cmdLine.AddArg(cTWCmdLine::ANAL_LEVEL, TSTRING(_T("Z")), TSTRING(_T("secure-mode")), cCmdLineParser::PARAM_ONE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModePolUpdate::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + // now do the stuff specific to this mode... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + TSTRING fullPath; + switch(iter.ArgId()) + { + case cTWCmdLine::TEXT_POL_FILE: + ASSERT(iter.NumParams() > 0); + mpData->mTextPolFile = iter.ParamAt(0); + // + // convert it to a full path + // + if( iFSServices::GetInstance()->FullPath( fullPath, mpData->mTextPolFile ) ) + mpData->mTextPolFile = fullPath; + break; + case cTWCmdLine::SITE_PASSPHRASE: + ASSERT(iter.NumParams() > 0); + mpData->mSitePassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mpData->mSiteProvided = true; + break; + case cTWCmdLine::ANAL_LEVEL: + ASSERT(iter.NumParams() > 0); + if(iter.ParamAt(0).compare(_T("high")) == 0) + mpData->mbAnal = true; + else if(iter.ParamAt(0).compare(_T("low")) == 0) + mpData->mbAnal = false; + else + { + // invalid parameter to anal switch... + // TODO -- print this to stderr; how do I display (1) the switch name + // and (2) the possible values? + // TODO -- move {high, low} somewhere else + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_BAD_PARAM) << _T(" : ") + << iter.ParamAt(0).c_str() << _T("; must be {high, low}") << std::endl; + return false; + } + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * site key file + // * policy file + // * db file + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), cTW, tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mSiteKeyFile.empty()), cTW, tw::STR_ERR_MISSING_SITE_KEY); + TEST_INIT_REQUIREMENT((! mpData->mPolFile.empty()), cTW, tw::STR_ERR_MISSING_POLICY); + TEST_INIT_REQUIREMENT((! mpData->mDbFile.empty()), cTW, tw::STR_ERR_MISSING_DB); + + // if a passphrase was passed on the command line, then late prompting should + // be set to false so that wrong passwords are detected immediately + // + // Note that the local passphrase was already checked against in FillOutCmdLineInfo(), + // so I only need to test the site passphrase + if( mpData->mSiteProvided && mpData->mbLatePassphrase ) + { + // TODO -- I don't know if we should display this or not -- mdb + //iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString( cTripwire, tripwire::STR_NOTIFY_CHANGE_PROMPT_TIME).c_str() ); + mpData->mbLatePassphrase = false; + } + + // make sure that the config file and site key file are in sync... + // + if (cTWUtil::VerifyCfgSiteKey( mstrConfigFile, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + + + #if IS_UNIX + // Set the cross file systems flag appropriately. + cFSDataSourceIter::SetFileSystemCrossing(mpData->mbCrossFileSystems); + #endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModePolUpdate::Execute(cErrorQueue* pQueue) +{ + try + { + // make sure all of the files are accessable + cFileUtil::TestFileWritable(mpData->mPolFile); + cFileUtil::TestFileWritable(mpData->mDbFile); + + // open and parse the new policy file... + cGenreSpecListVector genreSpecList; + cTWCmdLineUtil::ParseTextPolicyFile(genreSpecList, mpData->mTextPolFile, mpData->mSiteKeyFile, pQueue); + + cFCODatabaseFile dbFile; + cKeyFile localKeyfile, siteKeyfile; + cPrivateKeyProxy privateLocal, privateSite; + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + cTWUtil::OpenKeyFile(siteKeyfile, mpData->mSiteKeyFile); + + // open the old database; note that ReadDatabase will set bEncrypted and open the + // key file if necessary + bool bDbEncrypted; + bool bPolEncrypted = true; + + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), dbFile, localKeyfile.GetPublicKey(), bDbEncrypted); + + // + // give a warning if the user that created the database is not the same as the user running right now... + // + TSTRING userName; + if( iFSServices::GetInstance()->GetCurrentUserName( userName ) ) + { + if( dbFile.GetHeader().GetCreator().compare( userName.c_str() ) != 0 ) + { + // TODO -- move these strings to the string table + TOSTRINGSTREAM str; + str << TSS_GetString( cTripwire, tripwire::STR_ERR2_DIFFERENT_USERS1) << dbFile.GetHeader().GetCreator() + << TSS_GetString( cTripwire, tripwire::STR_ERR2_DIFFERENT_USERS2) << userName << std::ends; + cTWUtil::PrintErrorMsg( eICDifferentUsers( str.str(), eError::NON_FATAL ) ); + } + } + + // warn if the database is not encrytped + if(! bDbEncrypted && iUserNotify::GetInstance()->GetVerboseLevel() > iUserNotify::V_SILENT) + { + cTWUtil::PrintErrorMsg(eTWDbNotEncrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + + if( (!bDbEncrypted) && (mpData->mLocalProvided) ) + { + //Issue a warning if a passphrase has been supplied, and the database is NOT encrypted. + cTWUtil::PrintErrorMsg( eTWPassForUnencryptedDb( _T(""), eError::NON_FATAL)); + } + + + try + { + cFileManipulator polManipulator(mpData->mPolFile.c_str()); + polManipulator.Init(); + bPolEncrypted = polManipulator.GetEncoding() == cFileHeader::ASYM_ENCRYPTION; + } + catch (eError&) {} + + // + // get the passwords for early prompting + // + if(! mpData->mbLatePassphrase) + { + if(bDbEncrypted) + cTWUtil::CreatePrivateKey(privateLocal, localKeyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + + if(bPolEncrypted) + cTWUtil::CreatePrivateKey(privateSite, siteKeyfile, mpData->mSiteProvided ? mpData->mSitePassphrase.c_str() : 0, cTWUtil::KEY_SITE); + } + + + ///////////////////////////////////////////////////////// + // iterate through all the genres in the new policy... + ///////////////////////////////////////////////////////// + cFCODatabaseFile::iterator dbIter( dbFile ); + cGenreSpecListVector::iterator genreIter; + for (genreIter = genreSpecList.begin(); genreIter != genreSpecList.end(); ++genreIter) + { + // make this genre the current genre. + // + cGenreSwitcher::GetInstance()->SelectGenre( genreIter->GetGenre() ); + // + // seek the database iter to this genre... + // + dbIter.SeekToGenre( genreIter->GetGenre() ); + if( ! dbIter.Done() ) + { + // perform the policy update + // + cPolicyUpdate pu( genreIter->GetGenre(), dbIter.GetSpecList(), genreIter->GetSpecList(), dbIter.GetDb(), pQueue ); + uint32 puFlags = 0; + puFlags |= mpData->mbAnal ? cPolicyUpdate::ANAL : 0; + puFlags |= ( mpData->mbResetAccessTime ? cPolicyUpdate::FLAG_ERASE_FOOTPRINTS_PU : 0 ); + if( (! pu.Execute(puFlags)) && (mpData->mbAnal) ) + { + // they were in anal mode and errors occured; an error condition + TCOUT << TSS_GetString( cTripwire, tripwire::STR_ERR_POL_UPDATE) << std::endl; + return 8; + } + // we need to update the database's prop set... + // + dbIter.GetSpecList() = genreIter->GetSpecList(); + // + // TODO -- do some header stuff here? + // + } + else + { + // do a database init for this genre; it did not appear in the old policy... + // + TW_NOTIFY_NORMAL( TSS_GetString( cTripwire, tripwire::STR_PU_ADDING_GENRE ).c_str(), + cGenreSwitcher::GetInstance()->GenreToString( genreIter->GetGenre(), true ) ); + dbFile.AddGenre( genreIter->GetGenre(), &dbIter ); + + // copy the spec list to the database... + dbIter.GetSpecList() = genreIter->GetSpecList(); + + // generate the database... + // TODO -- turn pQueue into an error bucket + + uint32 gdbFlags = 0; + gdbFlags |= ( mpData->mbResetAccessTime ? cGenerateDb::FLAG_ERASE_FOOTPRINTS_GD : 0 ); + cGenerateDb::Execute( dbIter.GetSpecList(), dbIter.GetDb(), dbIter.GetGenreHeader().GetPropDisplayer(), pQueue, gdbFlags ); + + //TODO -- what other prop displayer stuff do I have to do here? + } + } + ////////////////////////////////////////////////////////////////////////////////////// + // now, we need to prune genres that are in the database but not in the new policy... + ////////////////////////////////////////////////////////////////////////////////////// + for( dbIter.SeekBegin(); ! dbIter.Done(); ) + { + bool bFoundGenre = false; + for (genreIter = genreSpecList.begin(); genreIter != genreSpecList.end(); ++genreIter) + { + if( genreIter->GetGenre() == dbIter.GetGenre() ) + { + bFoundGenre = true; + break; + } + } + if( ! bFoundGenre ) + { + // we need to remove this genre from the db... + // + dbIter.Remove(); + } + else + dbIter.Next() ; + } + + + // let's go ahead and update the database and policy file... + + // + // open the site key file and get the site passphrase + // + if(!privateSite.Valid() && bPolEncrypted) + cTWUtil::CreatePrivateKey(privateSite, siteKeyfile, mpData->mSiteProvided ? mpData->mSitePassphrase.c_str() : 0, cTWUtil::KEY_SITE); + // + // get the passphrase for the database, if necessary (it is important that we get both + // private keys before saving anything + // + if(bDbEncrypted && !privateLocal.Valid()) + { + ASSERT(mpData->mbLatePassphrase); + cTWUtil::CreatePrivateKey(privateLocal, localKeyfile, mpData->mLocalProvided ? mpData->mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + } + + // backup the file we are about to overwrite + cFileUtil::BackupFile(mpData->mPolFile); + + // + // write the policy file + // + cTWUtil::UpdatePolicyFile(mpData->mPolFile.c_str(), mpData->mTextPolFile.c_str(), bPolEncrypted, bPolEncrypted ? privateSite.GetKey() : 0); + + // + // update the header info + // + // Note: We DO NOT call cFCODatabaseUtil::CalculateHeader() here. We only + // want to update these entries. + dbFile.GetHeader().SetCreator(cTWUtil::GetCurrentUser()); + dbFile.GetHeader().SetPolicyFilename(mpData->mPolFile); + dbFile.GetHeader().SetConfigFilename(mstrConfigFile); + dbFile.GetHeader().SetLastDBUpdateTime( cSystemInfo::GetExeStartTime() ); + + // backup the file we are about to overwrite + cFileUtil::BackupFile(mpData->mDbFile); + + // + // write the db to disk... + // + cTWUtil::WriteDatabase(mpData->mDbFile.c_str(), dbFile, bDbEncrypted, bDbEncrypted ? privateLocal.GetKey() : 0); + } + catch(eError& e) + { + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_POLUP_FAIL_MSG ); + msg.append(cErrorTable::GetInstance()->Get( e.GetID() )); + + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_ERROR, msg.c_str()); + } + + cTWUtil::PrintErrorMsg(e); + return 8; + } + + if (mpData->mbLogToSyslog) + { + TSTRING msg = TSS_GetString( cTripwire, tripwire::STR_SYSLOG_POLUP_MSG ); + msg.append(mpData->mDbFile); + cSyslog::Log(TSS_GetString( cTripwire, tripwire::STR_SYSLOG_IDENT ).c_str(), cSyslog::LOG_SUCCESS, msg.c_str()); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWModePolUpdate::GetModeUsage( void ) +{ + return ( TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE_POLICY ) ); +} + +//############################################################################# +// cTWModeTest +//############################################################################# + +class cTWModeTest_i : public cTWModeCommon +{ +public: + cTWModeTest_i() : cTWModeCommon() { mMode=TEST_INVALID; } + + enum TestMode { TEST_INVALID, TEST_EMAIL }; + + TestMode mMode; + TSTRING mEmailAddress; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeTest::cTWModeTest() +{ + mpData = new cTWModeTest_i; +} + +cTWModeTest::~cTWModeTest() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeTest::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + // The only allowed test mode syntax so far is + // "tripwire --test --email name@domain.com" or "tripwire -t -e name@domain.com". + cmdLine.AddArg(cTWCmdLine::MODE_TEST, TSTRING(_T("")), TSTRING(_T("test")), cCmdLineParser::PARAM_NONE); + cmdLine.AddArg(cTWCmdLine::TEST_EMAIL, TSTRING(_T("e")), TSTRING(_T("email")), cCmdLineParser::PARAM_ONE); + + cmdLine.AddDependency( cTWCmdLine::MODE_TEST, cTWCmdLine::TEST_EMAIL ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeTest::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::TEST_EMAIL: + mpData->mMode = cTWModeTest_i::TEST_EMAIL; + mpData->mEmailAddress = iter.ParamAt(0); + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + // make sure that we have a valid operation + TEST_INIT_REQUIREMENT( ( mpData->mMode != cTWModeTest_i::TEST_INVALID ), cTripwire, tripwire::STR_ERR_NO_TEST_MODE ); + + if( mpData->mMode == cTWModeTest_i::TEST_EMAIL ) + { + // make sure that we have a valid mail method + TEST_INIT_REQUIREMENT( ( cMailMessage::NO_METHOD != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_NO_MAIL_METHOD ); + TEST_INIT_REQUIREMENT( ( cMailMessage::INVALID_METHOD != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_INVALID_MAIL_METHOD ); +#if !SUPPORTS_MAPI + TEST_INIT_REQUIREMENT( ( cMailMessage::MAIL_BY_MAPI != mpData->mMailMethod ), cTripwire, tripwire::STR_ERR_MAPI_NOT_SUPPORTED ); +#endif + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeTest::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWModeTest::Execute"); + + switch (mpData->mMode) + { + case cTWModeTest_i::TEST_EMAIL: + { + cTWCmdLineUtil::SendEmailTestMessage(mpData->mEmailAddress, mpData); + } + default: + // should I do anything, or just ignore this? + ; + } + + return 0; +} + +TSTRING cTWModeTest::GetModeUsage( ) +{ + return ( TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_TEST ) ); +} + +//############################################################################# +// cTWModeHelp +//############################################################################# + +class cTWModeHelp_i : public cTWModeCommon +{ +public: + cTWModeHelp_i() {} + ~cTWModeHelp_i() {} + + std::set< TSTRING > mModes; + // A set of modes to output usage statements for a specific mode. + std::set< TSTRING > mPrinted; + // A set for making sure we don't print the same help twice. +}; + + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeHelp::cTWModeHelp() +{ + mpData = new cTWModeHelp_i(); +} + +cTWModeHelp::~cTWModeHelp() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeHelp::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // We're only interested in one parameter, that being help. Anything else + // passed to this mode should be a cmdlineparser error. + cmdLine.AddArg(cTWCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY, true); + cmdLine.AddArg(cTWCmdLine::MODE_HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_HELP_ALL, TSTRING(_T("")), TSTRING(_T("all")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_INIT, TSTRING(_T("i")), TSTRING(_T("init")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_CHECK, TSTRING(_T("c")), TSTRING(_T("check")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_UPDATE_DB, TSTRING(_T("u")), TSTRING(_T("update")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_UPDATE_POL, TSTRING(_T("p")), TSTRING(_T("update-policy")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_TEST, TSTRING(_T("t")), TSTRING(_T("test")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_EXPLORE, TSTRING(_T("")), TSTRING(_T("explore")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWCmdLine::MODE_DEBUG, TSTRING(_T("")), TSTRING(_T("verify")), cCmdLineParser::PARAM_MANY); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeHelp::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + cCmdLineIter iter(cmdLine); + + // Grab the arguments from the help parameter: + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWCmdLine::MODE_HELP: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + { + mpData->mModes.insert( iter.ParamAt(i) ); + } + } + break; + case cTWCmdLine::MODE: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + { + mpData->mModes.insert( iter.ParamAt(i) ); + } + } + break; + // allow users to enter the mode + // names with "--" prepended. We have to do this, since + // the cmdlineparser treats them as switches. + case cTWCmdLine::MODE_HELP_ALL: // fall through + case cTWCmdLine::MODE_INIT: // fall through + case cTWCmdLine::MODE_CHECK: // fall through + case cTWCmdLine::MODE_UPDATE_DB: // fall through + case cTWCmdLine::MODE_UPDATE_POL: // fall through + case cTWCmdLine::MODE_TEST: // fall through + case cTWCmdLine::MODE_EXPLORE: // fall through + case cTWCmdLine::MODE_DEBUG: + { + int i; + // push back the parameter that was actually passed. + TSTRING str = iter.ActualParam(); + // Kill off the initial "--" or "-" + str.erase( 0, 1 ); + if( str.length() != 1) + str.erase( 0, 1 ); + + mpData->mModes.insert( str ); + for( i = 0; i < iter.NumParams(); ++i ) + mpData->mModes.insert( iter.ParamAt(i) ); + } + break; + default: + // should I do anything, or just ignore this? + // cmdlineparser will catch the bad args. + ; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeHelp::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWModeHelp::Execute"); + + // The iterator we will use to traverse the list of arguments: + std::set::iterator it = mpData->mModes.begin(); + + // We'll want to output the version information, regardless: + TCOUT << TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + + if( it == mpData->mModes.end() ) // all that was passed was --help + { + // Output a short usage summary for each mode. + TCOUT << TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_USAGE_SUMMARY ); + // + // That's it, return. + return 8; + } + + for( ; it != mpData->mModes.end(); ++it ) + { + if( _tcscmp( (*it).c_str(), _T("all")) == 0 ) + { + //Since --help all was passed, emit all help messages and return. + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_INIT ); + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_CHECK ); + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE ); + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE_POLICY ); + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_TEST ); +#ifdef _DEBUG_DB + // TODO: Do we need help messages for these modes? DRA +#endif + //We're done, return + return 8; + } + } + + //We need some subset of the usage statements. Figure out which modes have + //been specified: + it = mpData->mModes.begin(); + for( ; it != mpData->mModes.end(); ++it ) + { + // This is going to be ugly code... + if ( _tcscmp( (*it).c_str(), _T("init") ) == 0 || _tcscmp( (*it).c_str(), _T("i") ) == 0 ) + { + //make sure we don't print the same help twice... + if( mpData->mPrinted.find( _T("init") ) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_INIT ); + mpData->mPrinted.insert( _T("init") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("check") ) == 0 || _tcscmp( (*it).c_str(), _T("c") ) == 0 ) + { + if( mpData->mPrinted.find( _T("check") ) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_CHECK ); + mpData->mPrinted.insert( _T("check") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("update") ) == 0 || _tcscmp( (*it).c_str(), _T("u") ) == 0 ) + { + if( mpData->mPrinted.find( _T("update") ) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE ); + mpData->mPrinted.insert( _T("update") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("update-policy") ) == 0 || _tcscmp( (*it).c_str(), _T("p") ) == 0 ) + { + if( mpData->mPrinted.find( _T("update-policy") ) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_UPDATE_POLICY ); + mpData->mPrinted.insert( _T("update-policy") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("test") ) == 0 || _tcscmp( (*it).c_str(), _T("t") ) == 0 ) + { + if( mpData->mPrinted.find( _T("test") ) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTripwire, tripwire::STR_TRIPWIRE_HELP_TEST ); + mpData->mPrinted.insert( _T("test") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("explore") ) == 0 ) + TCOUT<< _T(""); //we currently don't have usage statements for this mode. + else if( _tcscmp( (*it).c_str(), _T("verify") ) == 0 ) + TCOUT<< _T(""); //we currently don't have usage statements for this mode. + else + { + cTWUtil::PrintErrorMsg( eTWHelpInvalidModeSwitch((*it), eError::NON_FATAL) ); + TCOUT << std::endl; + // emit error string, this mode does not exist + } + } + + //Everything went okay + return 8; +} + +//================================================================ +// UTIL FUNCTIONS +//================================================================ + +bool util_GetEditor( TSTRING& strEd ) +{ + // see if VISUAL environment var is set + TCHAR* pchEd = _tgetenv( _T("VISUAL") ); + if( pchEd != NULL && pchEd[0] != _T('\0') ) + { + strEd = pchEd; + return true; + } + + // see if EDITOR environment var is set + pchEd = _tgetenv( _T("EDITOR") ); + if( pchEd != NULL && pchEd[0] != _T('\0') ) + { + strEd = pchEd; + return true; + } + + return false; +} + +//Encase the explore and debug modes in this ifdef, since they are for internal +//use only. +#ifdef _DEBUG_DB + +//############################################################################# +// cTWModeExploreDb +//############################################################################# +#include "tw/dbexplore.h" + +class cTWModeExploreDb_i : public cTWModeCommon +{ +public: + cTWModeExploreDb_i() : cTWModeCommon() {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeExploreDb::cTWModeExploreDb() +{ + mpData = new cTWModeExploreDb_i; +} + +cTWModeExploreDb::~cTWModeExploreDb() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeExploreDb::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_EXPLORE, TSTRING(_T("")), TSTRING(_T("explore")), cCmdLineParser::PARAM_NONE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeExploreDb::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeExploreDb::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWModeExploreDb::Execute"); + + cFCODatabaseFile dbFile; + cFCODatabaseFile::iterator dbIter( dbFile ); + try + { + cKeyFile localKeyfile; + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + + bool bEncrypted; + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), dbFile, localKeyfile.GetPublicKey(), bEncrypted); + // + // seek to the first genre in the db... + // + dbIter.SeekBegin(); + if( dbIter.Done() ) + { + //TODO -- what is the right thing to do here? + // + ASSERT( false ); + throw eTWDbHasNoGenres(); + } + // + // ok, time to explore the database! + // + cDbExplore::Execute( dbIter ); + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + return 8; + } + + return 0; +} + +//############################################################################# +// cTWModeDebugDb +//############################################################################# +#include "tw/dbdebug.h" + +class cTWModeDebugDb_i : public cTWModeCommon +{ +public: + cTWModeDebugDb_i() : cTWModeCommon() {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWModeDebugDb::cTWModeDebugDb() +{ + mpData = new cTWModeDebugDb_i; +} + +cTWModeDebugDb::~cTWModeDebugDb() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWModeDebugDb::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // initialize the switches common to all modes... + InitCmdLineCommon(cmdLine); + + cmdLine.AddArg(cTWCmdLine::MODE_DEBUG, TSTRING(_T("")), TSTRING(_T("verifydb")), cCmdLineParser::PARAM_NONE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWModeDebugDb::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutConfigInfo(mpData, cf); + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWModeDebugDb::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWModeDebugDb::Execute"); + + cFCODatabaseFile dbFile; + cFCODatabaseFile::iterator dbIter( dbFile ); + try + { + cKeyFile localKeyfile; + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + + bool bEncrypted; + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), dbFile, localKeyfile.GetPublicKey(), bEncrypted); + // + // seek to the first genre in the db... + // + dbIter.SeekBegin(); + if( dbIter.Done() ) + { + //TODO -- what is the right thing to do here? + // + ASSERT( false ); + throw eTWDbHasNoGenres(); + } + // + // debug the database. + // + cDbDebug::Execute( dbIter, mpData->mDbFile ); + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + return 8; + } + + return 0; +} + + +#endif //_DEBUG_DB + + diff --git a/src/tripwire/twcmdline.h b/src/tripwire/twcmdline.h new file mode 100644 index 0000000..d571d3f --- /dev/null +++ b/src/tripwire/twcmdline.h @@ -0,0 +1,424 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twcmdline.h +// +// cTWCmdLine -- holds all information on tripwire's command line +// iTWMode -- abstract base class for a mode of operation in tripwire +#ifndef __TWCMDLINE_H +#define __TWCMDLINE_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __WCHAR16_H +#include "core/wchar16.h" +#endif + +#ifndef __MAILMESSAGE_H +#include "mailmessage.h" // used for email reporting +#endif + +#ifndef __TEXTREPORTVIEWER_H // for multiple levels of reporting +#include "tw/textreportviewer.h" +#endif + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +class cConfigFile; +class cCmdLineParser; +class cErrorQueue; +class cErrorBucket; +class iTWMode; +class cFCODatabaseFile; +class cFCOReport; +class cFCODbHeader; +class cFCOReportHeader; + +TSS_EXCEPTION( eTWHelpInvalidModeSwitch, eError ); +TSS_EXCEPTION( eTWInitialization, eError ); +TSS_EXCEPTION( eTWInvalidConfigFileKey, eError ); +TSS_EXCEPTION( eTWInvalidReportLevel, eError ); +TSS_EXCEPTION( eTWInvalidReportLevelCfg, eError ); +TSS_EXCEPTION( eTWInvalidPortNumber, eError ); +TSS_EXCEPTION( eTWPassForUnencryptedDb, eError ); +TSS_EXCEPTION( eTWInvalidTempDirectory, eError ); + +/////////////////////////////////////////////////////////////////////////////// +// cTWCmdLine -- class with a bunch of static member functions helpful in parsing +// the tripwire command line +/////////////////////////////////////////////////////////////////////////////// +class cTWCmdLine +{ +public: + //static void InitCmdLineParser(cCmdLineParser& parser); + // call this to initialize the command line parser + + static iTWMode* GetMode(int argc, const TCHAR *const * argv); + // this will look at the beginning of the command line, determine the appropriate + // mode to create, and returns it. If the mode can't be determined, an error message + // is printed and null is returned. + + // constants for all the command line arguments + enum CmdLineArgs + { + HELP, + + // modes + MODE, // generic -m + MODE_INIT, + MODE_CHECK, + MODE_UPDATE_DB, + MODE_UPDATE_POL, + MODE_TEST, + MODE_EXPLORE, + MODE_DEBUG, + MODE_HELP, + MODE_HELP_ALL, + MODE_VERSION, + + VERBOSE, + SILENT, + POL_FILE, + CFG_FILE, + SITE_KEY_FILE, + LOCAL_KEY_FILE, + DB_FILE, + REPORT_FILE, + LOOSE_DIRS, + NO_BACKUP, + NO_ENCRYPT, + INTER_UPDATE, // interactive update after integrity check + EDITOR, + NO_TTY, + MAIL_REPORT, + IGNORE_PROP, + ENCRYPT_REPORT, + SEVERITY_LEVEL, + //SEVERITY_NAME, + RULE_NAME, + GENRE_NAME, + ACCEPT_ALL, // update db with entire report + ANAL_LEVEL, + TEXT_POL_FILE, + LOCAL_PASSPHRASE, + SITE_PASSPHRASE, + TEST_EMAIL, + REPORTLEVEL, + +#ifdef GMMS + USE_GMMS, + GMMS_VERBOSITY, +#endif + + PARAMS, // the final parameters + + NUM_CMDLINEARGS + }; +}; + +//############################################################################# +// cTWModeCommon -- contains data common to all modes; all cTWMode*_i will +// derive from this class. +//############################################################################# +class cTWModeCommon +{ + public: + int mVerbosity; // must be 0 <= n <= 2 + wc16_string mLocalPassphrase; // pass phrase for private key + bool mLocalProvided; + TSTRING mPolFile; + TSTRING mSiteKeyFile; + TSTRING mLocalKeyFile; + TSTRING mDbFile; + TSTRING mReportFile; + TSTRING mEditor; + TSTRING mTempDirectory; // where we create our temp files... + TSTRING mGlobalEmail; // a list of email addr's + + bool mbLatePassphrase; // do we ask for the passphrase at the end of the operation or the beginning? + bool mfLooseDirs; // do we do loose directory checking? + bool mbResetAccessTime; // do we reset access time when calculating properties of files? + bool mbLogToSyslog; // log significant events and level 0 reports to SYSLOG + bool mbCrossFileSystems; // automatically recurse across mount points on Unis FS genre + + cTextReportViewer::ReportingLevel mEmailReportLevel; // What level of email reporting we should use + cMailMessage::MailMethod mMailMethod; // What mechanism should we use to send the report + + TSTRING mSmtpHost; // name of SMTP host to use + unsigned short mSmtpPort; // port number of that SMTP host + TSTRING mMailProgram; // full path to executable to use for piped mail + bool mMailNoViolations; // Email out reports with no violations? + + cTWModeCommon() : mVerbosity(1), + mLocalProvided(false), + mbLatePassphrase(false), + mfLooseDirs(false), + mbResetAccessTime(false), + mbLogToSyslog(false), + mbCrossFileSystems(false) + { + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// iTWMode -- base class that contains an interface for initializing tripwire +// in a mode of operation and executing in that mode; a class is derived +// from this for each mode of operation +/////////////////////////////////////////////////////////////////////////////// +class iTWMode +{ +public: + virtual void InitCmdLineParser(cCmdLineParser& cmdLine) = 0; + // fills out the command line parser with all the switches that are appropriate for + // the given mode. + virtual bool Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) = 0; + // call this to ask the mode object to initialize all of its data structures + // with the passed in information. If it returns false, it can be assumed that an error + // message was spit to stderr. + virtual int Execute(cErrorQueue* pQueue) = 0; + // go to work! TODO -- I don't know how errors (or return values) should be conveyed + // I think that maybe this guy should return an int indicating the return value + virtual TSTRING GetModeUsage( void ) = 0; + // Return a usage string particular to the concrete mode. + virtual cTWCmdLine::CmdLineArgs GetModeID() = 0; + // return the MODE_* enumeration for a given mode. + void SetCmdLine( const TSTRING& str ) { mstrCmdLine = str; }; + void SetConfigFile( const TSTRING& str ) { mstrConfigFile = str; }; + + virtual ~iTWMode() {}; +protected: + TSTRING mstrCmdLine; + TSTRING mstrConfigFile; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Database Initialization +/////////////////////////////////////////////////////////////////////////////// +class cTWModeDbInit_i; +class cTWModeDbInit : public iTWMode +{ +public: + cTWModeDbInit(); + virtual ~cTWModeDbInit(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( void ); + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_INIT; } +private: + cTWModeDbInit_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Integrity Check +/////////////////////////////////////////////////////////////////////////////// +class cTWModeIC_i; +class cTWModeIC : public iTWMode +{ +public: + enum { + ERROR_IC = 8 + }; + + cTWModeIC(); + virtual ~cTWModeIC(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ); + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_CHECK; } + +private: + cTWModeIC_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Database Update +/////////////////////////////////////////////////////////////////////////////// +class cTWModeDbUpdate_i; +class cTWModeDbUpdate : public iTWMode +{ +public: + cTWModeDbUpdate(); + virtual ~cTWModeDbUpdate(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + void Init (const cTWModeIC_i* pICData, cFCODatabaseFile* dbFile, cFCOReportHeader* prh, cFCOReport* pReport, bool bEncryptDb); + // this Init is used when you want to automatically launch into db update + // mode from integrity checking mode. It is called by cTWModeIC after it + // is totally done with the integrity check. + // The database and report are passed in becuase they are already loaded + // into memory when IC is done, so it doesn't make sense for this class to + // load them again. If bEncrypt is true, then the database should be encrypted when + // saved. + + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ); + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_UPDATE_DB; } + +private: + cTWModeDbUpdate_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Policy Update +/////////////////////////////////////////////////////////////////////////////// +class cTWModePolUpdate_i; +class cTWModePolUpdate : public iTWMode +{ +public: + cTWModePolUpdate(); + virtual ~cTWModePolUpdate(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ); + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_UPDATE_POL; } + +private: + cTWModePolUpdate_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Tripwire test mode +/////////////////////////////////////////////////////////////////////////////// +class cTWModeTest_i; +class cTWModeTest : public iTWMode +{ +public: + cTWModeTest(); + virtual ~cTWModeTest(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ); + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_TEST; } + +private: + cTWModeTest_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Tripwire help mode : Used to issue usage statements for a variable number +// of specific modes. +/////////////////////////////////////////////////////////////////////////////// +class cTWModeHelp_i; +class cTWModeHelp : public iTWMode +{ +public: + cTWModeHelp(); + virtual ~cTWModeHelp(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ) { return _T(""); } + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_HELP; } + +private: + cTWModeHelp_i* mpData; +}; + +//These two modes are invisible if _DEBUG_DB is not defined. +#ifdef _DEBUG_DB + +/////////////////////////////////////////////////////////////////////////////// +// Explore Db +/////////////////////////////////////////////////////////////////////////////// +class cTWModeExploreDb_i; +class cTWModeExploreDb : public iTWMode +{ +public: + cTWModeExploreDb(); + virtual ~cTWModeExploreDb(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ) { return _T(""); } + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_EXPLORE; } + +private: + cTWModeExploreDb_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// DebugDb +/////////////////////////////////////////////////////////////////////////////// +class cTWModeDebugDb_i; +class cTWModeDebugDb : public iTWMode +{ +public: + cTWModeDebugDb(); + virtual ~cTWModeDebugDb(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage( ) { return _T(""); } + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_DEBUG; } + +private: + cTWModeDebugDb_i* mpData; +}; + +#endif //_DEBUG_DB + +/////////////////////////////////////////////////////////////////////////////// +// Version Mode +/////////////////////////////////////////////////////////////////////////////// +class cTWModeVersion : public iTWMode +{ +public: + cTWModeVersion() {} + virtual ~cTWModeVersion() {} + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine) { ASSERT(false); } + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine) { ASSERT(false); return true; } + virtual int Execute (cErrorQueue* pQueue) { ASSERT(false); return 0; } + virtual TSTRING GetModeUsage( ) { ASSERT(false); return _T(""); } + virtual cTWCmdLine::CmdLineArgs GetModeID() { return cTWCmdLine::MODE_VERSION; } + +private: +}; + +#endif + diff --git a/src/tripwire/twcmdlineutil.cpp b/src/tripwire/twcmdlineutil.cpp new file mode 100644 index 0000000..7bd25af --- /dev/null +++ b/src/tripwire/twcmdlineutil.cpp @@ -0,0 +1,944 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// twcmdlineutil.cpp +#include "stdtripwire.h" + +#include "twcmdlineutil.h" + +#include "fco/fcospeclist.h" +#include "twparser/policyparser.h" +#include "twparser/parserhelper.h" // used in TripPropsFromSpecs below +#include "fco/parsergenreutil.h" +#include "fco/fcopropvector.h" +#include "core/fsservices.h" +#include "core/usernotify.h" +#include "tw/fcoreport.h" +#include "twcrypto/keyfile.h" +#include "tw/twutil.h" +#include "tw/textreportviewer.h" +#include "core/archive.h" +#include // used to open plain text policy file +#include "mailmessage.h" // used for email reporting +#include "fco/twfactory.h" +#include "tripwirestrings.h" +#include "twcmdline.h" +#include "fco/fcospecutil.h" +#include "integritycheck.h" +#include "fco/genreswitcher.h" +#include "tw/fcodatabasefile.h" +#include "core/errorgeneral.h" +#include "tw/twerrors.h" +#include "fco/fconametranslator.h" +#include "fco/iterproxy.h" +#include "core/twlocale.h" +#include "core/stringutil.h" +#include "tw/twstrings.h" +#include "tw/filemanipulator.h" +#include "core/displayencoder.h" + +#include + +#ifdef GMMS + +// local helper functions for GMMS notification +static TSTRING FormatGmmsReportSummary(int32 date, int violationCount, int maxSeverity); +static TSTRING FormatGmmsViolationSummary(int32 date, const TSTRING& rulename, const TSTRING& filename, int severity); +static void SendGmmsAlert(const TSTRING& gmmsProg, const TSTRING& gmmsOptions, const TSTRING& alerts); // throw (eGmmsError) + +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// ParsePolicyFile +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::ParsePolicyFile(cGenreSpecListVector& genreSpecList, const TSTRING& fileName, TSTRING& strSiteKeyFile, cErrorQueue* pQueue) +{ + // get site public key + cKeyFile siteKeyfile; + cTWUtil::OpenKeyFile( siteKeyfile, strSiteKeyFile ); + + // read in and unencrypt policy file + std::string strPolicyText; + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_POLICY_FILE).c_str(), + cDisplayEncoder::EncodeInline( fileName ).c_str() ); + + // warn user if policy file is unencrypted + { + cFileManipulator policyManipulator(fileName.c_str()); + policyManipulator.Init(); + if (policyManipulator.GetEncoding() != cFileHeader::ASYM_ENCRYPTION) + cTWUtil::PrintErrorMsg(eTWPolUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + + cTWUtil::ReadPolicyText( fileName.c_str(), strPolicyText, siteKeyfile.GetPublicKey() ); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_PARSING_POLICY).c_str(), + cDisplayEncoder::EncodeInline( fileName ).c_str()); + + // set up parser and parser policy file + std::istringstream in( strPolicyText ); + cPolicyParser parser( in ); + parser.Execute( genreSpecList, pQueue ); +} + +/////////////////////////////////////////////////////////////////////////////// +// ParseTextPolicyFile +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::ParseTextPolicyFile(cGenreSpecListVector& genreSpecList, const TSTRING& fileName, TSTRING& strSiteKeyFile, cErrorQueue* pQueue) +{ + std::ifstream in; + in.open(cStringUtil::TstrToStr(fileName).c_str()); + if(in.fail()) + { + throw eOpen( fileName ); + } + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_PARSING_POLICY).c_str(), + cDisplayEncoder::EncodeInline( fileName ).c_str()); + + cPolicyParser parser(in); + parser.Execute(genreSpecList, pQueue); +} + + +/////////////////////////////////////////////////////////////////////////////// +// util_NextPropToken +// +// gets the next token in the property string. Tokens are delimited by , or : and +// iff : is the delimiter, bGenreName is set to true. Returns an empty string when +// the end of the string is reached +/////////////////////////////////////////////////////////////////////////////// +static TSTRING util_NextPropToken(TSTRING::const_iterator& i, const TSTRING& src, bool& bGenreName) +{ + TSTRING ret; + TSTRING::const_iterator begin = i; + for(; i != src.end(); i++ ) + { + if( (*i == _T(':')) || (*i == _T(',')) ) + break; + } + if( (i == src.end()) || (*i != _T(':')) ) + bGenreName = false; + else + bGenreName = true; + ret.assign( begin, i ); + // + // move the iter to the beginning of the next token + // + if( i != src.end() ) + i++; + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// TrimPropsFromSpecs +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::TrimPropsFromSpecs(cFCOSpecList& specList, const TSTRING& propsToIgnore) +{ + cDebug d("cTWCmdLineUtil::TrimPropsFromSpecs"); + d.TraceDebug("Entering...\n"); + cFCOPropVector v; + iParserGenreUtil* pHelper = iTWFactory::GetInstance()->CreateParserGenreUtil(); + // + // trim only the properties appropriate for the current genre... + // + TSTRING propStr, ignoreStr; + cGenre::Genre sysGenre = cGenreSwitcher::GetInstance()->CurrentGenre(); + cGenre::Genre curGenre = cGenreSwitcher::GetInstance()->GetDefaultGenre(); + + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + TSTRING::const_iterator i = propsToIgnore.begin(); + TSTRING curToken; + bool bGenreName; + // + // the main token-getting loop + // + while( true ) + { + curToken = util_NextPropToken( i, propsToIgnore, bGenreName ); + if( curToken.empty() ) + break; // all done + // + // handle the genre switching token... + // + if( bGenreName ) + { + curGenre = cGenreSwitcher::GetInstance()->StringToGenre( curToken.c_str() ); + if( curGenre == cGenre::GENRE_INVALID ) + { + throw eTWUnknownSectionName( curToken ); + } + } + else + { + if( curGenre == sysGenre ) + { + // put together a string to pass to parsing code. + // Single letter properties can be simply concatenated, where + // long property names must have a '&' between them. + if( pGU->HasSingleLetterProps() ) + propStr += curToken; + else + propStr += _T("&") + curToken; + + // + // this string is used to tell the user what we are ignoring + // + if( ignoreStr.empty() ) + ignoreStr = curToken; + else + ignoreStr += _T(", ") + curToken; + } + } + } + // + // if there is nothing to remove, just return... + // + if( propStr.empty() ) + return; + + try + { + cParserUtil::CreatePropVector( propStr, v, pHelper ); + delete pHelper; + } + catch(eParserHelper&) + { + delete pHelper; + d.TraceError("CreatePropVector failed!!\n"); + throw eTWBadPropsToIgnore( propsToIgnore ); + } + + d.TraceDebug("We are ignoring these properties:\n"); + v.TraceContents(); + + iUserNotify::GetInstance()->Notify(1, _T("%s %s\n"), TSS_GetString( cTripwire, tripwire::STR_IGNORE_PROPS).c_str(), + cDisplayEncoder::EncodeInline( ignoreStr ).c_str()); + + + // okay, now let's change the specs! + cFCOSpecListAddedIter iter(specList); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + // TODO -- when we have multiple masks, we will need to iterate through all of the masks. + cFCOPropVector specVector = iter.Spec()->GetPropVector(iFCOSpecMask::GetDefaultMask()); + cFCOPropVector newSpecVector = (specVector & v) ^ specVector; + iter.Spec()->SetPropVector(iFCOSpecMask::GetDefaultMask(), newSpecVector); + + d.TraceDebug("Spec's prop set\n-----before:\n"); + specVector.TraceContents(); + d.TraceDebug("-----after:\n"); + newSpecVector.TraceContents(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TrimSpecsByName +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::TrimSpecsByName(cFCOSpecList& specList, const TSTRING specName) +{ + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_CHECKING_SPECS_NAMED).c_str(), + cDisplayEncoder::EncodeInline( specName ).c_str()); + + cFCOSpecListAddedIter iter(specList); + for(iter.SeekBegin(); ! iter.Done(); ) + { + //if(iter.Attr()->GetName().compare(specName) == 0) + // right now, names are stored in the spec, but soon they will be in the + // attributes (see commented out code above) + if(iter.Spec()->GetName().compare(specName) == 0) + { + // found one! + iter.Next(); + } + else + { + iter.Remove(); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TrimSpecsBySeverity +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::TrimSpecsBySeverity(cFCOSpecList& specList, int severity) +{ + cDebug d("cTWCmdLineUtil::TrimSpecsBySeverity"); + d.TraceDebug("Entering; severity=%d\n", severity); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + _T("%s%d\n"), + TSS_GetString( cTripwire, tripwire::STR_IC_SEVERITY_LEVEL).c_str(), + severity); + + cFCOSpecListAddedIter iter(specList); + for(iter.SeekBegin(); ! iter.Done(); ) + { + if(iter.Attr()->GetSeverity() < severity) + { + d.TraceDetail("Removing spec %s (severity=%d)\n", iter.Spec()->GetStartPoint().AsString().c_str(), + iter.Attr()->GetSeverity()); + + TW_NOTIFY_VERBOSE( TSS_GetString( cTripwire, tripwire::STR_IC_IGNORING_SEVERITY).c_str(), + iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay + ( iter.Spec()->GetStartPoint() ).c_str(), + iter.Attr()->GetSeverity()); + + iter.Remove(); + } + else + iter.Next(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TrimSpecsBySeverityName +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::TrimSpecsBySeverityName(cFCOSpecList& specList, const TSTRING& severity) +{ + // for now, the names are hard coded, but they might not be in the future... + if(_tcsicmp(severity.c_str(), _T("low")) == 0) + TrimSpecsBySeverity(specList, 33); + else if(_tcsicmp(severity.c_str(), _T("medium")) == 0) + TrimSpecsBySeverity(specList, 66); + else if(_tcsicmp(severity.c_str(), _T("high")) == 0) + TrimSpecsBySeverity(specList, 100); + else + { + throw eTWBadSeverityName( severity ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ReportContainsFCO +/////////////////////////////////////////////////////////////////////////////// +bool cTWCmdLineUtil::ReportContainsFCO(const cFCOReport& report) +{ + cFCOReportGenreIter genreIter( report ); + for(genreIter.SeekBegin(); ! genreIter.Done(); genreIter.Next()) + { + cFCOReportSpecIter specIter( genreIter ); + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + if( (! specIter.GetAddedSet()->IsEmpty()) || + (! specIter.GetRemovedSet()->IsEmpty()) || + ( specIter.GetNumChanged() != 0)) + return true; + } + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetICReturnValue +/////////////////////////////////////////////////////////////////////////////// +int cTWCmdLineUtil::GetICReturnValue(const cFCOReport& report ) +{ + enum { ADDED = 1, REMOVED = 2, CHANGED = 4 }; + + int rtn = 0; + cFCOReportGenreIter genreIter( report ); + for(genreIter.SeekBegin(); ! genreIter.Done(); genreIter.Next()) + { + cFCOReportSpecIter specIter(report, genreIter.GetGenre()); + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + if(! specIter.GetAddedSet()->IsEmpty()) + rtn |= ADDED; + if(! specIter.GetRemovedSet()->IsEmpty()) + rtn |= REMOVED; + if(specIter.GetNumChanged() != 0) + rtn |= CHANGED; + } + } + return rtn; +} + +/////////////////////////////////////////////////////////////////////////////// +// VerifySpecs +// +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::VerifySpecs( const cFCOSpecList& parsedList, const cFCOSpecList& dbList ) +{ + cFCOSpecListCanonicalIter policyItr (parsedList); + cFCOSpecListCanonicalIter dbItr (dbList); + + if( parsedList.Size() != dbList.Size() ) + { + throw eICBadPol(); + } + + for ( policyItr.SeekBegin(), dbItr.SeekBegin(); ! policyItr.Done(); policyItr.Next(), dbItr.Next() ) + { + if( ! iFCOSpecUtil::FCOSpecEqual(*policyItr.Spec(), *dbItr.Spec()) ) + { + throw eICBadPol(); + } + // make sure the vectors are the same... + // TODO -- this won't work when we get spec masks + // + if( policyItr.Spec()->GetPropVector( iFCOSpecMask::GetDefaultMask() ) != + dbItr.Spec()->GetPropVector( iFCOSpecMask::GetDefaultMask() ) ) + { + throw eICBadPol(); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// VerifyPolicy +/////////////////////////////////////////////////////////////////////////////// +void cTWCmdLineUtil::VerifyPolicy( cGenreSpecListVector& genreSpecList, cFCODatabaseFile& dbFile ) +{ + cGenreSpecListVector::iterator genreIter; + cFCODatabaseFile::iterator dbIter( dbFile ); + + // make sure the number of genres in each is the same. + // + if( genreSpecList.size() != (size_t)dbIter.Size() ) + throw eICBadPol(); + + // iterate over all of the genres... + // + for (genreIter = genreSpecList.begin(); genreIter != genreSpecList.end(); ++genreIter) + { + dbIter.SeekToGenre( genreIter->GetGenre() ); + if( dbIter.Done() ) + { + throw eICBadPol(); + } + // now, compare the two property sets... + // + VerifySpecs( genreIter->GetSpecList(), dbIter.GetSpecList()); + + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// GetEmailRecipients - produce a list of all email addresses referred to in +// the report. +// +//////////////////////////////////////////////////////////////////////////////// +static void GetEmailRecipients(std::vector &vstrRecipients, + const cFCOReport& report, + const cTWModeCommon *modeCommon) { + + // loop through all generes + cFCOReportGenreIter genreIter(report); + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) { + + // loop through all specs + cFCOReportSpecIter specIter(report, genreIter.GetGenre()); + + for (specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) { + + // loop through all email addresses for this spec + cFCOSpecAttrEmailIter emailIter(*specIter.GetAttr()); + + for(emailIter.SeekBegin(); ! emailIter.Done(); emailIter.Next()) { + + TSTRING address = emailIter.EmailAddress(); + std::vector::iterator i; + + // see if the address is already in the list + i = std::find(vstrRecipients.begin(), + vstrRecipients.end(), + address); + + if (i == vstrRecipients.end()) { + vstrRecipients.push_back(address); + } + + } + } + } +} + + +static void GetGlobalEmailRecipients(std::vector &vstrRecipients, + const cFCOReport& report, + const cTWModeCommon *modeCommon) { + + + // let's check for global emailto's... + // + if (modeCommon->mGlobalEmail.length() != 0) { + + std::vector addys; + const std::string delims = ";,"; + + cStringUtil::splitstring(addys, modeCommon->mGlobalEmail, delims); + + while (!addys.empty()) { + + std::vector::iterator p; + TSTRING addr = addys.back(); + + // make sure it's not already in there... + // + p = std::find(vstrRecipients.begin(), + vstrRecipients.end(), + addr); + + // put it away if it's unique... + // + if (p == vstrRecipients.end()) { + vstrRecipients.push_back(addr); + } + + addys.pop_back(); // remove that one... + + } + } + +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// EmailReportTo - send only the relevant portions of the report the address +// +/////////////////////////////////////////////////////////////////////////////// +static bool EmailReportTo(const TSTRING &toAddress, const cFCOReportHeader& header, const cFCOReport& report, + const cTWModeCommon *modeCommon, + const bool bForceFullReport) +{ + std::auto_ptr reportMail; + + // allocate the right kind of emailer object based on what came out of the config file. + switch (modeCommon->mMailMethod) + { + default: + ASSERT(false); + return false; + case cMailMessage::MAIL_BY_SMTP: + reportMail = std::auto_ptr(new cSMTPMailMessage(modeCommon->mSmtpHost, modeCommon->mSmtpPort)); + break; + case cMailMessage::MAIL_BY_PIPE: + reportMail = std::auto_ptr(new cPipedMailMessage(modeCommon->mMailProgram)); + break; + case cMailMessage::MAIL_BY_MAPI: +#if SUPPORTS_MAPI + reportMail = std::auto_ptr(new cMAPIMailMessage); + break; +#else + ASSERT(false); + return false; +#endif + } + + TSTRING strTempFilename; + + // send the report + try + { + // we have to write the text report to a temporary file... + iFSServices::GetInstance()->GetTempDirName( strTempFilename ); + strTempFilename += _T("tripwire-report-XXXXXX"); + iFSServices::GetInstance()->MakeTempFilename( strTempFilename ); + strTempFilename += _T(".txt"); + + // print the report + cEmailReportViewer trv( header, report, toAddress, bForceFullReport ); + trv.PrintTextReport( strTempFilename, modeCommon->mEmailReportLevel ); + + // format the subject line with number of violations and the most severe violation found + // set up the cMailMessage class, and send it if they need it or want it + // (Yes, it seems odd to generate the report, only to potentially delete it without sending it.) + if ( trv.GetNumberViolations() > 0 || modeCommon->mMailNoViolations ) + { + // print message that we're emailing to this specific recipient + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s %s\n"), + TSS_GetString( cTripwire, tripwire::STR_EMAIL_REPORT_TO).c_str(), + cDisplayEncoder::EncodeInline( toAddress ).c_str()); + reportMail->AddRecipient(toAddress); + + TSTRING machineName; + iFSServices::GetInstance()->GetMachineNameFullyQualified(machineName); + reportMail->SetFrom(TSS_GetString( cTripwire, tripwire::STR_EMAIL_FROM) + machineName); + reportMail->SetFromName(TSS_GetString(cTW, tw::STR_TSS_PRODUCT_NAME)); + + reportMail->SetSubject( trv.SingleLineReport() ); + + // don't attach a report if the user just requests a subject line + if( cTextReportViewer::SINGLE_LINE == modeCommon->mEmailReportLevel ) + reportMail->SetBody( _T(" ") ); + else + reportMail->AttachFile( strTempFilename.c_str() ); + + reportMail->Send(); + } + + // delete temp file + iFSServices::GetInstance()->FileDelete( strTempFilename ); + } + catch(eError& e) + { + e.SetFatality( false ); // we want to continue from email errors, so make them non-fatal + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_EMAIL_REPORT) << std::endl; + // delete temp file + iFSServices::GetInstance()->FileDelete( strTempFilename ); + return false; + } + + return true; +} + + +static bool DoEmailReports(const std::vector &vstrRecipients, + const cFCOReportHeader& header, + const cFCOReport& report, + const cTWModeCommon *modeCommon, + const bool bForceFullReport) { + + // send each report out. + bool ret = true; + for (std::vector::size_type i=0; iNotify( iUserNotify::V_NORMAL, _T("%s\n"), + TSS_GetString( cTripwire, + tripwire::STR_EMAIL_BEGIN).c_str()); + + bool emailSent = false; + bool ret = true; + + // Get the list of recipients + std::vector vstrRecipients; + + GetEmailRecipients(vstrRecipients, report, modeCommon); + emailSent |= (vstrRecipients.size() != 0); + + if (vstrRecipients.size() != 0) + ret = DoEmailReports(vstrRecipients, header, report, modeCommon, false); + + if (ret) { // if not, probably catostrophic + + vstrRecipients.clear(); + GetGlobalEmailRecipients(vstrRecipients, report, modeCommon); + emailSent |= (vstrRecipients.size() != 0); + + if (vstrRecipients.size() != 0) + ret = DoEmailReports(vstrRecipients, header, report, modeCommon, true); + + } + + + if (!emailSent) { + + // Send a message to the user, alerting them that no email has been sent. + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NO_EMAIL_RECIPIENTS).c_str()); + } + + return ret; +} + + +bool cTWCmdLineUtil::SendEmailTestMessage(const TSTRING &mAddress, const cTWModeCommon *modeCommon) +{ + std::auto_ptr reportMail; + + // allocate the right kind of emailer object based on what came out of the config file. + switch (modeCommon->mMailMethod) + { + default: + ASSERT(false); + return false; + case cMailMessage::MAIL_BY_SMTP: + reportMail = std::auto_ptr(new cSMTPMailMessage(modeCommon->mSmtpHost, modeCommon->mSmtpPort)); + break; + case cMailMessage::MAIL_BY_PIPE: + reportMail = std::auto_ptr(new cPipedMailMessage(modeCommon->mMailProgram)); + break; + case cMailMessage::MAIL_BY_MAPI: +#if SUPPORTS_MAPI + reportMail = std::auto_ptr(new cMAPIMailMessage); + break; +#else + ASSERT(false); + return false; +#endif + } + + + // print message that we're emailing to this specific recipient + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s %s\n"), + TSS_GetString( cTripwire, tripwire::STR_TEST_EMAIL_TO).c_str(), + cDisplayEncoder::EncodeInline( mAddress ).c_str()); + + // send the report + try + { + // set up the cMailMessage class, and send it + reportMail->AddRecipient(mAddress); + + TSTRING machineName; + iFSServices::GetInstance()->GetMachineNameFullyQualified(machineName); + reportMail->SetFrom(TSS_GetString( cTripwire, tripwire::STR_EMAIL_FROM) + machineName); + reportMail->SetFromName(TSS_GetString(cTW, tw::STR_TSS_PRODUCT_NAME)); + + reportMail->SetSubject (TSS_GetString( cTripwire, tripwire::STR_TEST_EMAIL_SUBJECT)); + reportMail->SetBody (TSS_GetString( cTripwire, tripwire::STR_TEST_EMAIL_BODY)); + reportMail->Send(); + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString( cTripwire, tripwire::STR_ERR_EMAIL_TEST) << std::endl; + return false; + } + + return true; +} + + +#ifdef GMMS + +// +// Use gmms to send violation notification +// +// verbosity==1 One line summary of whole report +// verbosity==2 One line summary of each violation +// +bool cTWCmdLineUtil::GmmsReport(const cFCOReportHeader& header, const cFCOReport& report, + const TSTRING &gmmsProg, const TSTRING &gmmsOptions, int verbosity) // throw (eGmmsError) +{ + int violationCount = 0, maxSeverity = 0; + TSTRING alerts; + + // loop through all generes + cFCOReportGenreIter genreIter(report); + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) + { + // loop through all specs + cFCOReportSpecIter specIter(report, genreIter.GetGenre()); + for (specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + + ASSERT(true); + + // Get severity + int32 severity = specIter.GetAttr()->GetSeverity(); + + // Get rulename + TSTRING rulename = specIter.GetAttr()->GetName(); + + // Go through all of the added file rule violations + cIterProxy addedIter(specIter.GetAddedSet()->GetIter()); + for (addedIter->SeekBegin(); !addedIter->Done(); addedIter->Next()) + { + if (severity > maxSeverity) + maxSeverity = severity; + + if (verbosity == 2) + { + // get filename, send one line summary of this violation + TSTRING filename = addedIter->FCO()->GetName().AsString(); + alerts += FormatGmmsViolationSummary(header.GetCreationTime(), rulename, filename, severity); + alerts += _T("\n"); + } + + violationCount++; + } + + // Go through all of the removed file rule violations + cIterProxy removedIter(specIter.GetRemovedSet()->GetIter()); + for (removedIter->SeekBegin(); !removedIter->Done(); removedIter->Next()) + { + if (severity > maxSeverity) + maxSeverity = severity; + + if (verbosity == 2) + { + // get filename, send one line summary of this violation + TSTRING filename = removedIter->FCO()->GetName().AsString(); + alerts += FormatGmmsViolationSummary(header.GetCreationTime(), rulename, filename, severity); + alerts += _T("\n"); + } + + violationCount++; + } + + // Go through all of the changed file rule violations + cFCOReportChangeIter changedIter(specIter); + for (changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next()) + { + if (severity > maxSeverity) + maxSeverity = severity; + + if (verbosity == 2) + { + // get filename, send one line summary of this violation + TSTRING filename = changedIter.GetOld()->GetName().AsString(); + alerts += FormatGmmsViolationSummary(header.GetCreationTime(), rulename, filename, severity); + alerts += _T("\n"); + } + + violationCount++; + } + } + } + + // Send one line summary of the whole report if that's what they want, + // or if there were no violations and the verbosity level is 2. That way + // verbosity level 2 and no violations will still send an all-is-well notification. + if (verbosity == 1 || (verbosity == 2 && violationCount==0)) + { + alerts += FormatGmmsReportSummary(header.GetCreationTime(), violationCount, maxSeverity); + alerts += _T("\n"); + } + + ASSERT(!alerts.empty()); + SendGmmsAlert(gmmsProg, gmmsOptions, alerts); + + return true; +} + + +// +// Use this with gmms verbosity level 1 +// +TSTRING FormatGmmsReportSummary(int32 date, int violationCount, int maxSeverity) +{ + TSTRING strDate; + cTWLocale::FormatTime(date, strDate); + + TOSTRINGSTREAM summary; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_START); + summary << strDate; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_VERBOSITY1A); + summary << violationCount; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_VERBOSITY1B); + summary << maxSeverity; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_END); + + return summary.str(); +} + + +// +// Use this with gmms verbosity level 2 +// +TSTRING FormatGmmsViolationSummary(int32 date, const TSTRING& rulename, const TSTRING& filename, int severity) +{ + TSTRING strDate; + cTWLocale::FormatTime(date, strDate); + + TOSTRINGSTREAM summary; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_START); + summary << strDate; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_VERBOSITY2A); + summary << rulename; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_VERBOSITY2B); + summary << filename; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_VERBOSITY2C); + summary << severity; + summary << TSS_GetString( cTripwire, tripwire::STR_GMMS_END); + + return summary.str(); +} + +static void SendGmmsAlert(const TSTRING& gmmsProg, const TSTRING& gmmsOptions, const TSTRING& alerts) // throw (eGmmsError) +{ +#if IS_UNIX + + // construct the command line for starting gmms + TSTRING command = gmmsProg + _T(" ") + gmmsOptions; + + // preserve environment variables necessary for gmms to run + le_set("GEOPLEX_DEPLOY"); + le_set("LD_LIBRARY_PATH"); + le_set("PATH"); + + // open the process + FILE *mpFile = mpopen((char*)command.c_str(), _T("w")); + if(!mpFile) + throw eGmmsError(eGmmsError::ERR_COULDNT_OPEN_PIPE, gmmsProg); + + // write the alert(s) to the process's standard-in. + if (_ftprintf(mpFile, "%s", alerts.c_str()) < 0) + throw eGmmsError(eGmmsError::ERR_COULDNT_WRITE_TO_PIPE, gmmsProg); + + // end the process by closing standard-in + int result = mpclose( mpFile ); + if (result != 0) + { + // complain about gmms returning an error code. + throw eGmmsError(eGmmsError::ERR_CMD_FAILED, gmmsProg); + } + + // unset environment variables necessary for gmms to run + le_unset("GEOPLEX_DEPLOY"); + le_unset("LD_LIBRARY_PATH"); + le_unset("PATH"); + +#else + + // GMMS is not for NT, so just do something cheap and easy for debugging purposes. + std::cerr << cStringUtil::TstrToStr(alerts); + +#endif +} + +#endif + diff --git a/src/tripwire/twcmdlineutil.h b/src/tripwire/twcmdlineutil.h new file mode 100644 index 0000000..398cea8 --- /dev/null +++ b/src/tripwire/twcmdlineutil.h @@ -0,0 +1,114 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twcmdlineutil.h +// +// cTWCmdLineUtil -- helper functions that twcmdline.cpp uses... +#ifndef __TWCMDLINEUTIL_H +#define __TWCMDLINEUTIL_H + +#include "mailmessage.h" +#include "core/error.h" + +class cFCOSpecList; +class cGenreSpecListVector; +class cErrorQueue; +class cFCOReport; +class cFCOReportHeader; +class cTWModeCommon; +class cErrorBucket; +class cFCODatabaseFile; + +TSS_EXCEPTION( eGmmsError, eError ); +TSS_EXCEPTION( eGmmsCouldntOpenPipe, eGmmsError ); +TSS_EXCEPTION( eGmmsCouldntWritePipe, eGmmsError ); +TSS_EXCEPTION( eGmmsCmdFailed, eGmmsError ); + +class cTWCmdLineUtil +{ +public: + + static void ParsePolicyFile(cGenreSpecListVector& genreSpecList, const TSTRING& fileName, TSTRING& strSiteKeyFile, cErrorQueue* pQueue); // throw (eError) + // this parses the given (encrypted) policy file and puts the results into the passed in specList. If an error occurs, + // pQueue will be filled up and an exception will be thrown. + // Note: If the policy file is not encrypted, an warning message will be printed to standard error. + static void ParseTextPolicyFile(cGenreSpecListVector& genreSpecList, const TSTRING& fileName, TSTRING& strSiteKeyFile, cErrorQueue* pQueue); // throw (eError) + // same as ParsePolicyFile above, but it expects a plain text policy file as input. Used during policy update + // mode + + static void TrimPropsFromSpecs(cFCOSpecList& specList, const TSTRING& propsToIgnore); // throw (eError) + // converts propsToIgnore into a property vector and removes all the properties in the + // vector from all specs in specList; throws eError() the string is in an invalid format. + static void TrimSpecsByName(cFCOSpecList& specList, const TSTRING specName); // throw (eError) + // removes all specs from the list whose name doesn't match specName. If every name is + // removed from the spec list, an error msg is printed and eError is thrown + static void TrimSpecsBySeverity(cFCOSpecList& specList, int severity); // throw (eError) + // removes all specs from the list whose severity is less than the passed in value. + // If every name is removed from the spec list, an error msg is printed and eError is thrown + static void TrimSpecsBySeverityName(cFCOSpecList& specList, const TSTRING& severity); // throe (eError) + // converts the severity name to a number and calls TrimSpecsBySeverity(). Prints an error + // message and throws eError() if it falis (can't convert name to int) + static bool ReportContainsFCO(const cFCOReport& report); + // returns true if the report contains at least one FCO in it. + + static int GetICReturnValue(const cFCOReport& report); + // determines the appropriate return value for an integrity check; the following + // values are ORed together to produce the final return value: + // 1 = files were added + // 2 = files were removed + // 4 = files were changed + + static bool EmailReport(const cFCOReportHeader& header, const cFCOReport& report, const cTWModeCommon *modeCommon); + // email all interested parties the contents of this report, by opening a pipe to + // the given email program (sendmail or some other MTA) and writing the report in + // its text form. This only works in unix. + // if an error occurs, then a message is displayed and false is returned + + static bool SendEmailTestMessage(const TSTRING &mAddress, const cTWModeCommon *modeCommon); + // email a test message to the specified address + + static void VerifyPolicy( cGenreSpecListVector& genreSpecList, cFCODatabaseFile& dbFile );//throw (eError) + // makes sure that the given policy is appropriate for the given database. It is appropriate if it is + // _exactly_ the same, including equal numbers and types of genres. + static void VerifySpecs( const cFCOSpecList& parsedList, const cFCOSpecList& dbList );//throw (eError) + // determines whether the policy in the policy file (parsedList) is equal to the database's current + // policy (dbList). If it is not, an exception is thrown + +#ifdef GMMS + static bool GmmsReport(const cFCOReportHeader& header, const cFCOReport& report, + const TSTRING &gmmsProg, const TSTRING &gmmsOptions, int verbosity); // throw (eGmmsError) + // Use gmms to send violation notification +#endif +}; + +#endif + diff --git a/src/tripwire/updatedb.cpp b/src/tripwire/updatedb.cpp new file mode 100644 index 0000000..1ef2ff3 --- /dev/null +++ b/src/tripwire/updatedb.cpp @@ -0,0 +1,230 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// updatedb.cpp +#include "stdtripwire.h" +#include "tripwirestrings.h" +#include "updatedb.h" +#include "db/hierdatabase.h" +#include "tw/dbdatasource.h" +#include "core/errorbucket.h" +#include "tw/fcoreport.h" +#include "core/debug.h" +#include "fco/genreswitcher.h" +#include "fco/iterproxy.h" +#include "fco/fcocompare.h" +#include "fco/fcopropset.h" +#include "fco/fco.h" +#include "core/usernotify.h" +#include "tripwireutil.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" + +//============================================================================= +// class cUpdateDb +//============================================================================= + +cUpdateDb::cUpdateDb( cHierDatabase& db, cFCOReport& report, cErrorBucket* pBucket ) +: mDb ( db ), + mReport ( report ), + mpBucket( pBucket ) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +bool cUpdateDb::Execute( uint32 flags ) +{ + cDebug d("cUpdateDb::Execute"); + bool bResult = true; + + // I will assume that the current genre is correct... + // + cFCOReportSpecIter specIter( mReport, cGenreSwitcher::GetInstance()->CurrentGenre() ); + cDbDataSourceIter dbIter ( &mDb ); + dbIter.SetErrorBucket(mpBucket); + iFCONameTranslator* pTrans = iTWFactory::GetInstance()->GetNameTranslator(); + + // + // set flags + // + if( flags & FLAG_ERASE_FOOTPRINTS_UD ) + { + dbIter.SetIterFlags( iFCODataSourceIter::DO_NOT_MODIFY_OBJECTS ); + } + + // + // iterate through all the specs... + // + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next()) + { + // skip this spec if there is nothing to update... + // + if( (specIter.GetAddedSet()->IsEmpty()) && + (specIter.GetRemovedSet()->IsEmpty()) && + (specIter.GetNumChanged() == 0) ) + { + continue; + } + // + // Add all of the "Added" files... + // + cIterProxy fcoIter (specIter.GetAddedSet()->GetIter()); + for(fcoIter->SeekBegin(); ! fcoIter->Done(); fcoIter->Next()) + { + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_DB_ADDING ).c_str(), + pTrans->ToStringDisplay( fcoIter->FCO()->GetName() ).c_str() ); + // + // seek to the new FCO, creating the path if necessary.. + // + dbIter.CreatePath( fcoIter->FCO()->GetName() ); + // + // report an error if this already exists in the db + // + if( dbIter.HasFCOData() ) + { + d.TraceError(_T("Report says to add fco %s that already exists in the db!\n"), fcoIter->FCO()->GetName().AsString().c_str()); + if( mpBucket ) + mpBucket->AddError( eUpdateDbAddedFCO( pTrans->ToStringDisplay( fcoIter->FCO()->GetName() ), + eError::SUPRESS_THIRD_MSG) ); + bResult = false; + } + else + { + // add the fco to the database... + // + d.TraceDebug(_T(">>> Adding FCO %s\n"), fcoIter->FCO()->GetName().AsString().c_str()); + dbIter.SetFCOData( fcoIter->FCO() ); + } + } + // + // remove all of the "Removed" files + // + cIterProxy rmIter(specIter.GetRemovedSet()->GetIter()); + for(rmIter->SeekBegin(); ! rmIter->Done(); rmIter->Next()) + { + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_DB_REMOVING ).c_str(), + pTrans->ToStringDisplay( rmIter->FCO()->GetName() ).c_str() ); + + + if(! cTripwireUtil::RemoveFCOFromDb( rmIter->FCO()->GetName(), dbIter ) ) + { + d.TraceError(_T("Report says to remove fco %s that doesn't exist in the db!\n"), rmIter->FCO()->GetName().AsString().c_str()); + if( mpBucket ) + mpBucket->AddError( eUpdateDbRemovedFCO( pTrans->ToStringDisplay( rmIter->FCO()->GetName() ), + eError::SUPRESS_THIRD_MSG) ); + bResult = false; + } + } + // + // change all the "Changed" fcos.... + // + cFCOCompare compareObj; + cFCOReportChangeIter changeIter(specIter); + for(changeIter.SeekBegin(); ! changeIter.Done(); changeIter.Next()) + { + TW_NOTIFY_VERBOSE( _T("%s%s\n"), + TSS_GetString( cTripwire, tripwire::STR_NOTIFY_DB_CHANGING ).c_str(), + pTrans->ToStringDisplay( changeIter.GetOld()->GetName() ).c_str() ); + + d.TraceDebug(">>> Changing FCO %s\n", changeIter.GetOld()->GetName().AsString().c_str()); + // + // error if the fco isn't in the database + // + dbIter.SeekToFCO( changeIter.GetOld()->GetName() ); + if( dbIter.Done() || ( ! dbIter.HasFCOData() ) ) + { + d.TraceError("Report says to change fco %s but it doesn't exist in the db!\n", + changeIter.GetOld()->GetName().AsString().c_str()); + if( mpBucket ) + mpBucket->AddError( eUpdateDbRemovedFCO( pTrans->ToStringDisplay( changeIter.GetOld()->GetName() ), + eError::SUPRESS_THIRD_MSG) ); + bResult = false; + continue; + } + // make sure that the fco properties match the "old" value in the report + // + iFCO* pDbFCO = dbIter.CreateFCO(); + compareObj.SetPropsToCmp(changeIter.GetOld()->GetPropSet()->GetValidVector()); + if( (compareObj.Compare(changeIter.GetOld(), pDbFCO) & cFCOCompare::EQUAL) == 0 ) + { + d.TraceError("FCO %s in report doesn't match current db values for properties!\n", + changeIter.GetOld()->GetName().AsString().c_str()); + changeIter.GetOld()->TraceContents (cDebug::D_ERROR); + pDbFCO->TraceContents (cDebug::D_ERROR); + if( mpBucket ) + mpBucket->AddError( eUpdateDbChangedFCO( pTrans->ToStringDisplay( pDbFCO->GetName() ), + eError::SUPRESS_THIRD_MSG) ); + pDbFCO->Release(); + bResult = false; + continue; + } + // + // ok, we can finally update the database... + // TODO -- I only think that we should be copying all of the properties if FLAG_REPLACE_PROPS + // is set. For example, what if they ignore a property? This bears some investigation... + //dbFcoIter->FCO()->GetPropSet()->CopyProps(changeIter.GetNew()->GetPropSet(), changeIter.GetNew()->GetPropSet()->GetValidVector()); + // + dbIter.RemoveFCOData(); + if( flags & FLAG_REPLACE_PROPS ) + { + // replace the old fco's data with the new data + // + dbIter.SetFCOData( changeIter.GetNew() ); + } + else + { + iFCO* pNewFCO = changeIter.GetNew()->Clone(); + // + // we need to fold in all properties that are in the old FCO but not valid in the new one + // (in case an integrity check ignored certain properties, we need to keep the old values in the + // database) -- 5 feb 99 mdb + // + cFCOPropVector propsToCopy = pDbFCO->GetPropSet()->GetValidVector() ^ + pNewFCO->GetPropSet()->GetValidVector(); + propsToCopy &= pDbFCO->GetPropSet()->GetValidVector(); + pNewFCO->GetPropSet()->CopyProps( pDbFCO->GetPropSet(), propsToCopy ); + + dbIter.SetFCOData( pNewFCO ); + + pNewFCO->Release(); + } + pDbFCO->Release(); + + } + } + + + return bResult; +} diff --git a/src/tripwire/updatedb.h b/src/tripwire/updatedb.h new file mode 100644 index 0000000..9e5fd97 --- /dev/null +++ b/src/tripwire/updatedb.h @@ -0,0 +1,88 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// updatedb.h +// +#ifndef __UPDATEDB_H +#define __UPDATEDB_H + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +class cHierDatabase; +class cFCOReport; +class cErrorBucket; + +//////////////////////////////////////////////////////////// +// Update Db Exceptions +//////////////////////////////////////////////////////////// +TSS_EXCEPTION( eUpdateDb, eError ); +TSS_EXCEPTION( eUpdateDbAddedFCO, eUpdateDb ); +TSS_EXCEPTION( eUpdateDbRemovedFCO, eUpdateDb ); +TSS_EXCEPTION( eUpdateDbChangedFCO, eUpdateDb ); + +class cUpdateDb +{ +public: + cUpdateDb( cHierDatabase& db, cFCOReport& report, cErrorBucket* pBucket ); + + bool Execute( uint32 flags = 0 ); + // returns false if there were any conflicts in updating + // the database + // TODO -- what kind of exceptions can come up from here? + + enum Flags + { + FLAG_REPLACE_PROPS = 0x00000001, + // if this flag is passed to execute, then them + // database's FCO's property set is completely + // replaced with the reports property set. + // (That means that invalid properties in the + // report will be invalidated in the database. + // This behavior is only desireable right now for + // policy update, when we want to get rid of stale + // information) + FLAG_ERASE_FOOTPRINTS_UD = 0x00000002 + // when this flag is set, UpdateDb will attempt + // undo any inadvertant modifications it may make + // when executing. + }; + +private: + cHierDatabase& mDb; + cFCOReport& mReport; + cErrorBucket* mpBucket; +}; + +#endif + diff --git a/src/tw/Makefile.am b/src/tw/Makefile.am new file mode 100644 index 0000000..30eb44b --- /dev/null +++ b/src/tw/Makefile.am @@ -0,0 +1,17 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libtw.a +libtw_a_SOURCES = \ + configfile.cpp dbdatasource.cpp dbdebug.cpp dbexplore.cpp \ + fcodatabasefile.cpp fcodatabaseutil.cpp fcoreport.cpp \ + fcoreportutil.cpp filemanipulator.cpp headerinfo.cpp \ + policyfile.cpp stdtw.cpp systeminfo.cpp textdbviewer.cpp \ + textreportviewer.cpp tw.cpp twerrors.cpp twinit.cpp \ + twstrings.cpp twutil.cpp + +DEFS = @DEFS@ -DCONFIG_DIR=\"$(sysconfdir)\" + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtw_a_OBJECTS) diff --git a/src/tw/Makefile.in b/src/tw/Makefile.in new file mode 100644 index 0000000..478b7ea --- /dev/null +++ b/src/tw/Makefile.in @@ -0,0 +1,409 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libtw_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/tw +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libtw_a_AR = $(AR) $(ARFLAGS) +libtw_a_LIBADD = +am_libtw_a_OBJECTS = configfile.$(OBJEXT) dbdatasource.$(OBJEXT) \ + dbdebug.$(OBJEXT) dbexplore.$(OBJEXT) \ + fcodatabasefile.$(OBJEXT) fcodatabaseutil.$(OBJEXT) \ + fcoreport.$(OBJEXT) fcoreportutil.$(OBJEXT) \ + filemanipulator.$(OBJEXT) headerinfo.$(OBJEXT) \ + policyfile.$(OBJEXT) stdtw.$(OBJEXT) systeminfo.$(OBJEXT) \ + textdbviewer.$(OBJEXT) textreportviewer.$(OBJEXT) tw.$(OBJEXT) \ + twerrors.$(OBJEXT) twinit.$(OBJEXT) twstrings.$(OBJEXT) \ + twutil.$(OBJEXT) +libtw_a_OBJECTS = $(am_libtw_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libtw_a_SOURCES) +DIST_SOURCES = $(libtw_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ -DCONFIG_DIR=\"$(sysconfdir)\" +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libtw.a +libtw_a_SOURCES = \ + configfile.cpp dbdatasource.cpp dbdebug.cpp dbexplore.cpp \ + fcodatabasefile.cpp fcodatabaseutil.cpp fcoreport.cpp \ + fcoreportutil.cpp filemanipulator.cpp headerinfo.cpp \ + policyfile.cpp stdtw.cpp systeminfo.cpp textdbviewer.cpp \ + textreportviewer.cpp tw.cpp twerrors.cpp twinit.cpp \ + twstrings.cpp twutil.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tw/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/tw/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libtw.a: $(libtw_a_OBJECTS) $(libtw_a_DEPENDENCIES) + -rm -f libtw.a + $(libtw_a_AR) libtw.a $(libtw_a_OBJECTS) $(libtw_a_LIBADD) + $(RANLIB) libtw.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtw_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/tw/configfile.cpp b/src/tw/configfile.cpp new file mode 100644 index 0000000..d9d7670 --- /dev/null +++ b/src/tw/configfile.cpp @@ -0,0 +1,723 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// configfile.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdtw.h" +#include "configfile.h" +#include "core/fsservices.h" +#include "core/hashtable.h" +#include "twcrypto/cryptoarchive.h" +#include "core/fileheader.h" +#include "core/timeconvert.h" +#include "tw/systeminfo.h" +#include "tw/twstrings.h" +#include "tw/twutil.h" +#include "core/charutil.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include +#include + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// UTIL FUNCTION PROTOTYPES +//========================================================================= + +static bool PopNextLine( TSTRING& fileIn, TSTRING& sLine, int& nLine ); +static bool IsReturnChar( TCHAR tch ); +static bool IsComment( const TSTRING& sLine ); +static void GetKeyValuePair( const TSTRING& sLine, TSTRING& sKey, TSTRING& sVal ); // throw( eConfigFile ); +static TSTRING& util_MakeTripwireDateString( TSTRING& strBuf ); + +//========================================================================= +// UTIL FUNCTIONS +//========================================================================= + +static bool IsReturnChar( TCHAR tch ) +{ + return( tch == _T('\n') || tch == _T('\r') ); +} + +static bool IsWhiteSpace( TCHAR tch ) +{ + return( ( tch >= 0x09 && tch <= 0x0D ) || tch == 0x20 ); +} + +static bool IsPoundSymbol( TCHAR tch ) +{ + return( tch == _T('#') ); +} + +static bool IsRightParen( TCHAR tch ) +{ + return( tch == _T(')') ); +} + +static bool IsLeftParen( TCHAR tch ) +{ + return( tch == _T('(') ); +} + +static bool IsDollarSign( TCHAR tch ) +{ + return( tch == _T('$') ); +} + +static bool IsEqualsSign( TCHAR tch ) +{ + return( tch == _T('=') ); +} + +static bool IsSingleTchar( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( first + 1 == last ); +} + +static bool IsReturnChar( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsReturnChar( *first ) + ); +} + +static bool IsWhiteSpace( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsWhiteSpace( *first ) + ); +} + + +static bool IsPoundSymbol( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsPoundSymbol( *first ) + ); +} + +static bool IsRightParen( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsRightParen( *first ) + ); +} + +static bool IsLeftParen( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsLeftParen( *first ) + ); +} + +static bool IsDollarSign( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsDollarSign( *first ) + ); +} + +static bool IsEqualsSign( TSTRING::const_iterator first, + TSTRING::const_iterator last ) +{ + return( + IsSingleTchar( first, last ) + && + IsEqualsSign( *first ) + ); +} + + +//========================================================================= +// METHOD CODE +//========================================================================= + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cConfigFile::cConfigFile() : + mStringHashTable(HASH_VERY_SMALL), mnLine(1) +{ + // we make the hash table very small (17 slots) because we don't expect very many things + // in the config file -- mdb +} + +cConfigFile::~cConfigFile() +{ + +} + + +void cConfigFile::WriteString( TSTRING& configText ) // throw( eFSServices ) +{ + TOSTRINGSTREAM out; + + TSTRING sKey, sVal; + cHashTableIter< TSTRING, TSTRING > hashTableIter( mStringHashTable ); + + // for all name-value pairs, print them out as "name=value\n" + for( hashTableIter.SeekBegin(); ! hashTableIter.Done(); hashTableIter.Next() ) + { + sKey = hashTableIter.Key(); + sVal = hashTableIter.Val(); + + out << sKey << _T("=") << sVal << _T("\n"); + } + + configText = out.str(); + + return; +} + +void cConfigFile::ReadString(const TSTRING configText) // throw( eConfigFile ); +{ +#ifdef _DEBUG + // NOTE:BAM -- debug only code ! + TCERR << _T("*** begin config text ***") << std::endl; + TCERR << configText << std::endl; + TCERR << _T("*** end config text ***") << std::endl; + TCERR << std::endl; + // NOTE:BAM -- debug only code ! +#endif + + TSTRING sLine; + TSTRING sConfigBuf; + for( sConfigBuf = configText; + PopNextLine( sConfigBuf, sLine, mnLine ); + sLine.erase() ) + { + // ignore comments + if( ! IsComment( sLine ) ) + { + TSTRING sKey, sVal; + + GetKeyValuePair( sLine, sKey, sVal ); + DoVarSubst( sVal ); + mStringHashTable.Insert( sKey, sVal ); + } + } + + CheckThatAllMandatoryKeyWordsExists(); + +#ifdef _DEBUG + // NOTE:BAM -- debug only code ! + TSTRING sTemp; + WriteString( sTemp ); + TCERR << _T("*** begin config read as ***") << std::endl; + TCERR << sTemp << std::endl; + TCERR << _T("*** end config read as ***") << std::endl; + TCERR << std::endl; + // NOTE:BAM -- debug only code ! +#endif + + return; +} + +bool cConfigFile::Lookup( const TSTRING& sKey, TSTRING& sVal ) const +{ + bool fFound = false; + + if( mStringHashTable.Lookup( sKey, sVal ) ) + { + // key was found + fFound = true; + } + + return( fFound ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFileHeaderID() +/////////////////////////////////////////////////////////////////////////////// + +struct cConfigFileFHID { + cFileHeaderID* configID; + + cConfigFileFHID() { configID = 0; } + ~cConfigFileFHID() { delete configID; } +} gConfigFileFHID; + +const cFileHeaderID& cConfigFile::GetFileHeaderID() +{ + if (gConfigFileFHID.configID == 0) + gConfigFileFHID.configID = new cFileHeaderID(_T("cConfigFile")); + + // sanity check + ASSERT(*gConfigFileFHID.configID == cFileHeaderID(_T("cConfigFile"))); + + return *gConfigFileFHID.configID; +} + +//========================================================================= +// UTIL FUNCTION CODE +//========================================================================= + +static bool PopNextLine( TSTRING& sIn, TSTRING& sLine, int& nLine ) +{ + bool fGotNextLine = false; + + TSTRING::const_iterator cur = sIn.begin(); // pointer to working position in sIn + const TSTRING::const_iterator end = sIn.end(); // end of sIn + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + // eat up all return chars + // while peek next char (does not update cur) + while( cCharUtil::PeekNextChar( cur, end, first, last ) ) + { + // is it a return char? (all return chars are single char) + if( IsSingleTchar( first, last ) ) + { + if( _T('\n') == *first ) + { + // eat up return and increment line number + nLine++; + cCharUtil::PopNextChar( cur, end, first, last ); + } + else if( _T('\r') == *first ) + { + // eat up return but don't count it as another line + cCharUtil::PopNextChar( cur, end, first, last ); + } + else + { + // not a return char. now get line + break; + } + } + else + { + // not a return char. now get line + break; + } + } + + // get line + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + if( ! IsReturnChar( first, last ) ) + { + fGotNextLine = true; // we'll say we've got the next line if we get at least one char + sLine.append( first, last ); + } + else + { + // either eof or a return char found, exit loop + break; + } + } + // 'first' is either end of line or return character + + // Pop line of of input string + TSTRING sTmp; + sTmp.assign( first, end ); + sIn = sTmp; + + return( fGotNextLine ); +} + + +static bool IsComment( const TSTRING& sLine ) +{ + TSTRING::const_iterator cur = sLine.begin(); // pointer to working position in sLine + const TSTRING::const_iterator end = sLine.end(); // end of sLine + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + // while pop next char (updates cur) + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + if( ! IsWhiteSpace( first, last ) ) + break; + } + + // it is a comment if it is an empty line or it starts with a # + return( first == end || IsPoundSymbol( first, last ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// TrimSpace -- trims leading and trailing whitespace from a string +/////////////////////////////////////////////////////////////////////////////// +static void TrimSpace(TSTRING& s) +{ + TSTRING::const_iterator cur = s.begin(); // pointer to working position in s + const TSTRING::const_iterator end = s.end(); // end of s + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + TSTRING::const_iterator firstNW = end; // identifies beginning of first non-whitespace character + TSTRING::const_iterator firstTW = end; // identifies beginning of first trailing whitespace character + + // find first non-whitespace char + while( cCharUtil::PeekNextChar( cur, end, first, last ) ) + { + if( IsWhiteSpace( first, last ) ) + { + cCharUtil::PopNextChar( cur, end, first, last ); + } + else + { + break; + } + } + if( first == end ) // no non-whitespace char, so lose it all + { + s.erase(); + return; + } + + // (first,last] now identify first non-whitespace character + firstNW = first; + + // find first of trailing whitespace + bool fInWhitespace = false; + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + if( IsWhiteSpace( first, last ) ) + { + if( ! fInWhitespace ) + { + firstTW = first; + } + // else we already know the beginning of the whitespace + + fInWhitespace = true; + } + else + { + fInWhitespace = false; + firstTW = end; // clear old trailing WS marker + } + } + ASSERT( first == end ); + ASSERT( firstNW < firstTW ); + + TSTRING sTmp; + sTmp.assign( firstNW, firstTW ); + s = sTmp; +} + +void cConfigFile::GetKeyValuePair( const TSTRING& sLine, TSTRING& sKey, TSTRING& sVal ) // throw (eConfigFile) +{ + // erase old values + sKey.erase(); + sVal.erase(); + + TSTRING::const_iterator cur = sLine.begin(); // pointer to working position in sLine + const TSTRING::const_iterator end = sLine.end(); // end of sLine + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + while( cCharUtil::PopNextChar( cur, end, first, last ) ) + { + if( IsEqualsSign( first, last ) ) + { + break; + } + } + + if( first == end ) + { + throw eConfigFileNoEq( MakeErrorString() ); + } + + + // get the two strings.. + sKey.assign( sLine.begin(), first ); + sVal.assign( last, sLine.end() ); + + // trim the white space from the beginning and end... + TrimSpace( sKey ); + TrimSpace( sVal ); + + // + // find more errors + // + // 1. empty key string + // 2. assignment to a predefined var + // + // allow empty values, but emit warning + // + TSTRING tstrDummy; + + if( sKey.empty() ) + { + throw eConfigFileNoKey( MakeErrorString() ); + } + else if( IsPredefinedVar( sKey, tstrDummy ) ) + { + throw eConfigFileAssignToPredefVar + ( MakeErrorString( sKey ) ); + } + else if( sVal.empty() ) + { + cTWUtil::PrintErrorMsg( eConfigFileEmptyVariable( MakeErrorString( sKey ), eError::NON_FATAL ) ); + } + + // everything went ok. +} + + +/////////////////////////////////////////////////////////////////////////////// +// DoVarSubst() +// replaces any $(VAR) with either built-in functions, or in the cfg symbol table +// fails if symbol isn't found +/////////////////////////////////////////////////////////////////////////////// + +void cConfigFile::DoVarSubst( TSTRING& s ) const //throw( eConfigFile ) +{ + cDebug d("cConfigFile::DoVarSubst()"); + d.TraceDebug( _T("ORIG: %s\n"), s.c_str() ); + + TSTRING sOut; + + // walk through string + // look for $( + // find matching ) + // pick out subset + // look up in symbol table + // substitute subset + // continue iterating + + + TSTRING::const_iterator cur = s.begin(); // pointer to working position in s + const TSTRING::const_iterator end = s.end(); // end of s + TSTRING::const_iterator first = end; // identifies beginning of current character + TSTRING::const_iterator last = end; // identifies end of current character + + // look for '$(' + do + { + if( cCharUtil::PeekNextChar( cur, end, first, last ) && + IsDollarSign( first, last ) ) + { + cCharUtil::PopNextChar( cur, end, first, last ); + + if( cCharUtil::PeekNextChar( cur, end, first, last ) && + IsLeftParen( first, last ) ) + { + TSTRING::const_iterator firstRP = end; // identifies beginning of rparen character + TSTRING::const_iterator lastRP = end; // identifies end of rparen character + + // [first,last) now identifies left paren + while( cCharUtil::PeekNextChar( cur, end, firstRP, lastRP ) ) + { + if( IsRightParen( firstRP, lastRP ) ) + break; + else + cCharUtil::PopNextChar( cur, end, firstRP, lastRP ); + } + // [firstRP,lastRP) identifies right paren + + if( ! IsRightParen( firstRP, lastRP ) ) + { + throw eConfigFileMissingRightParen( MakeErrorString( s ) ); + } + + // now get text between parens + TSTRING sVarName; + sVarName.assign( last, firstRP ); + d.TraceDebug( _T("symbol = %s\n"), sVarName.c_str() ); + + // look up in symbol table + TSTRING sVarValue; + if( ! IsPredefinedVar( sVarName, sVarValue ) && ! mStringHashTable.Lookup( sVarName, sVarValue ) ) + { + throw eConfigFileUseUndefVar( MakeErrorString( sVarName ) ); + } + + sOut += sVarValue; + } + else + { + sOut.append( first, last ); + } + } + else + { + sOut.append( first, last ); + } + } + while( cCharUtil::PopNextChar( cur, end, first, last ) ); + + d.TraceDebug( _T("DONE: %s\n"), sOut.c_str()); + s = sOut; +} + + +bool cConfigFile::IsPredefinedVar( const TSTRING& var, TSTRING& val ) const +{ + bool fRecognizeVar = false; + + if( 0 == var.compare( _T("HOSTNAME") ) ) + { + fRecognizeVar = true; + try + { + iFSServices::GetInstance()->GetMachineName( val); + if (val.empty()) + val = _T("localhost"); + } + catch( eFSServices& ) + { + val = _T("localhost"); + } + } + else if( 0 == var.compare( _T("DATE") ) ) + { + util_MakeTripwireDateString( val ); + fRecognizeVar = true; + } + + return( fRecognizeVar ); +} + +void cConfigFile::CheckThatAllMandatoryKeyWordsExists() // throw( eConfigFile ) +{ + TSTRING astrMandatoryKeys[] = + { + // I don't think ROOT should be manditory, since we don't really use it + // for anything -- mdb + //_T("ROOT"), + _T("POLFILE"), + _T("DBFILE"), + _T("REPORTFILE"), + _T("SITEKEYFILE"), + _T("LOCALKEYFILE"), +#ifdef GMMS + _T("GMMS"), + _T("GMMSOPTIONS") +#endif + }; + + + TSTRING strNotFound; + bool fAllFound = true; + + for( int i = 0; i < (int)countof(astrMandatoryKeys); i++ ) + { + TSTRING strDummy; + if( !mStringHashTable.Lookup( astrMandatoryKeys[i], strDummy ) || + strDummy.empty() ) + { + strNotFound += astrMandatoryKeys[i]; + strNotFound += _T(" "); + // key was found + fAllFound = false; + } + } + + if( ! fAllFound ) + { + throw eConfigFileMissReqKey( MakeErrorString( strNotFound, false ) ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// MakeErrorString +/////////////////////////////////////////////////////////////////////////////// +TSTRING cConfigFile::MakeErrorString( const TSTRING& strMsg, bool fShowLineNum ) const +{ + TOSTRINGSTREAM strErr; + + strErr << strMsg; + + if( fShowLineNum ) + { + // separate the message from the line number + if( ! strMsg.empty() ) + strErr << _T(": "); + + // output the line number + strErr << TSS_GetString( cTW, tw::STR_CUR_LINE ) << mnLine; + } + + return strErr.str(); +} + +TSTRING& util_MakeTripwireDateString( TSTRING& strBuf ) +{ + struct tm* ptmLocal = cTimeUtil::TimeToDateLocal( cSystemInfo::GetExeStartTime() ); + TOSTRINGSTREAM ostr; + ostr.imbue( std::locale::classic() ); + + // format is YYYYMMDD-HHMMSS + ostr.fill( _T('0') ); + ostr << std::setw(4) << ptmLocal->tm_year + 1900; + ostr << std::setw(2) << ptmLocal->tm_mon + 1; + ostr << std::setw(2) << ptmLocal->tm_mday; + ostr << _T("-"); + ostr << std::setw(2) << ptmLocal->tm_hour; + ostr << std::setw(2) << ptmLocal->tm_min; + ostr << std::setw(2) << ptmLocal->tm_sec; + + strBuf = ostr.str(); + + return strBuf; +} diff --git a/src/tw/configfile.h b/src/tw/configfile.h new file mode 100644 index 0000000..2dc61b5 --- /dev/null +++ b/src/tw/configfile.h @@ -0,0 +1,198 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// configfile.h +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __CONFIGFILE_H +#define __CONFIGFILE_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif//__TCHAR_H + +#ifndef __ERROR_H +#include "core/error.h" +#endif//__ERROR_H + +#ifndef __HASHTABLE_H +#include "core/hashtable.h" +#endif//__HASHTABLE_H + +#ifndef __FSSERVICES_H +#include "core/fsservices.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif//__DEBUG_H + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class eFSServices; +class cElGamalSigPrivateKey; +class cElGamalSigPublicKey; +class cFileHeaderID; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +TSS_EXCEPTION( eConfigFile, eError ); +TSS_EXCEPTION( eConfigFileNoEq, eConfigFile ); +TSS_EXCEPTION( eConfigFileNoKey, eConfigFile ); +TSS_EXCEPTION( eConfigFileAssignToPredefVar, eConfigFile ); +TSS_EXCEPTION( eConfigFileUseUndefVar, eConfigFile ); +TSS_EXCEPTION( eConfigFileMissReqKey, eConfigFile ); +TSS_EXCEPTION( eConfigFileEmptyVariable, eConfigFile ); +TSS_EXCEPTION( eConfigFileMissingRightParen, eConfigFile ); + +/////////////////////////////////////////////////////////////////////////////// +// cConfigFile +// +// use this class read and write key/value pairs to and from a file. +// it reads ([\r\n]+)-separated "key=value" pairs from a file +// it writes pairs "Insert"ed into it +// comments are specified by lines that match /$\s*#/ -- note that this does +// not allow for comments after a name/value pair. +/////////////////////////////////////////////////////////////////////////////// +class cConfigFile +{ +public: + cConfigFile(); + virtual ~cConfigFile(); + + bool Lookup( const TSTRING& tstrKey, TSTRING& tstrVal ) const; + // returns true if key is found in internal container and returns its value in tstrVal. + void WriteString( TSTRING& configText ); + // writes all key/value pairs from internal container to filename as "name=value\n" + void ReadString( const TSTRING configText ); // throw( eConfigFile ); + // reads "name=value[\r\n]+" from file and puts all pairs into internal container + + static const cFileHeaderID& GetFileHeaderID(); + // Return a cFileHeaderID for all databases + +private: + void GetKeyValuePair( const TSTRING& tstrLine, TSTRING& tstrKey, TSTRING& tstrVal ); // throw (eConfigFile) + bool IsPredefinedVar( const TSTRING& var, TSTRING& val ) const; + void DoVarSubst( TSTRING& rval ) const; //throw( eConfigFile ) + void CheckThatAllMandatoryKeyWordsExists(); // throw( eConfigFile ) + + TSTRING MakeErrorString( const TSTRING& strMsg = _T(""), bool fShowLineNum = true ) const; + // conststructs an error string. Appends "Line number: X" + // if fShowLineNum is true + // This string can then be passed to the exception ctor. + + cHashTable< TSTRING, TSTRING > mStringHashTable; + friend class cConfigFileIter; + int mnLine; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// cConfigFileIter -- iterate over the entries in the config file +// +// NOTE -- this class is not tested at all! +/////////////////////////////////////////////////////////////////////////////// +class cConfigFileIter +{ +public: + cConfigFileIter( cConfigFile& cf); + virtual ~cConfigFileIter(); + + void SeekBegin() const; + bool Done() const; + void Next() const; + const TSTRING& Key() const; + TSTRING& Val(); +protected: + cHashTableIter mIter; +}; + +//----------------------------------------------------------------------------- +// inline implementation +//----------------------------------------------------------------------------- +inline cConfigFileIter::cConfigFileIter( cConfigFile& cf) : + mIter( cf.mStringHashTable ) +{ + mIter.SeekBegin(); +} + +inline cConfigFileIter::~cConfigFileIter() +{ +} + +inline void cConfigFileIter::SeekBegin() const +{ + mIter.SeekBegin(); +} + +inline bool cConfigFileIter::Done() const +{ + return mIter.Done(); +} + +inline void cConfigFileIter::Next() const +{ + mIter.Next(); +} + +inline const TSTRING& cConfigFileIter::Key() const +{ + ASSERT(! Done()); + return mIter.Key(); +} + +inline TSTRING& cConfigFileIter::Val() +{ + ASSERT(! Done()); + return mIter.Val(); +} + + + +#endif //__CONFIGFILE_H + diff --git a/src/tw/configfile_t.cpp b/src/tw/configfile_t.cpp new file mode 100644 index 0000000..fab208c --- /dev/null +++ b/src/tw/configfile_t.cpp @@ -0,0 +1,191 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +//configfile_t.cpp : a test driver for cConfigFile +// +//Don't see a test driver for this module in source safe - +//hopefully this hasn't been implemented already! -DA + +#include "stdtw.h" +#include "configfile.h" +#include "core/errorbucketimpl.h" +#include "test/test.h" +#include "core/debug.h" +#include +#include "core/fsservices.h" +#include "fco/fconame.h" +#include "tw/twutil.h" + +using namespace std; + +void TestConfigFile(void) +{ + TSTRING asConfigFileText[] = + { + _T("BRIAN=foo"), // 0 fine + _T("BRIAN=foo\nBILL=bar"), // 1 fine + _T("BRIAN=foo\r\nBILL=bar"), // 2 fine + _T("BRIAN=foo\n\n\rBILL=bar\n"),// 3 fine + _T(" WS=foo \n\n\r BILL=bar\n"), // 4 fine + _T(" WS = foo \n\n\r BILL = bar \n"), // 5 fine + _T("FOO=foo\nBAR=$(FOO)"), // 6 fine + _T("FOO=foo\nBAR=$(FO)"), // 7 undefined var + _T("FOO=foo\nBAR=$(FOO"), // 8 no r paren + _T("FOO=foo\nBAR=$(FOO "), // 9 no r paren + _T("BAR=$(FOO\n"), // 10 no r paren + _T(" VAR =foo \nWS = $(VAR)\n"), // 11 fine + _T(""), // 12 fine + _T("\n"), // 13 fine + _T("\r"), // 14 fine + _T("\r\n"), // 15 fine + _T("B=POO\nA"), // 16 no equals + _T(" B=POO \n A \r"), // 17 no equals + _T("B=POO\nB=CRAP"), // 18 redefined var + _T("DATE=CRAP"), // 19 redefine predefine var + _T("B=POO\nDATE=CRAP"), // 20 redefine predefine var + _T("A=1\nB=$(A)\nC=$(B)"), // 21 fine -- checking var sub + _T("A=$(DATE)"), // 22 fine -- checking predef var sub + _T("A=1\nB=$(A)\nC=$(DATE)"), // 23 fine -- checking predef var sub + _T("A=1\n=$(A)\nC=$(DATE)"), // 24 no key + _T("A=$(DATE)-B"), // 25 fine -- check that the '-' shows up + _T("A=$(DATE)-$(DATE)"), // 26 fine -- check that the '-' shows up + }; + + /* + TSTRING sMandatory = \ + _T("\nPOLFILE=foo") \ + _T("\nDBFILE=foo") \ + _T("\nREPORTFILE=foo") \ + _T("\nSITEKEYFILE=foo") \ + _T("\nLOCALKEYFILE=foo"); + */ + + + for( TSTRING* at = &asConfigFileText[0]; + at != &asConfigFileText[countof(asConfigFileText)]; + at++ ) + { + cConfigFile cfg; + //*at += sMandatory; + + TCERR << _T("*** line:") << std::endl; + TCERR << *at << std::endl; + TCERR << _T("*** eol:") << std::endl; + try + { + cfg.ReadString( *at ); + } + catch( eConfigFileMissReqKey& ) + { + // ignore.... + } + catch( eConfigFile& e ) + { + int offset = ( at - asConfigFileText ); + int itemSize = sizeof( asConfigFileText[0] ); + int num = offset / itemSize; + TCERR << num << std::endl; + cTWUtil::PrintErrorMsg( e ); + } + } + +#ifdef NOT_BRIANS_TEST + cDebug d("Testconfigfile"); + d.TraceDetail("Entering...\n"); + iFSServices* pFSServices = iFSServices::GetInstance(); + + //Define some test values for pairs to be + //stored in a test config. module. I'm going to use the + //values specified in the install doc. -DA + TSTRING currpath; + pFSServices->GetCurrentDir(currpath); + const TSTRING testTWROOT = currpath; + const TSTRING testTWBIN = (testTWROOT + _T("/bin/")); + const TSTRING testTWCFG = (testTWROOT + _T("/etc/")); + const TSTRING testTWMAN = (testTWROOT + _T("/man/")); + const TSTRING testTWHTML = (testTWROOT + _T("/html/")); + const TSTRING testTWDB = (testTWROOT + _T("/db/")); + const TSTRING testTWKEY = (testTWROOT + _T("/key/")); + const TSTRING testTWREPORT = (testTWROOT + _T("/report/")); + const TSTRING testTWPASSWORD = (testTWROOT + _T("/null_password")); + + //Begin tests of config. module parser: + cConfigFile write_cfgmod; + //Filename for writing/reading some value pairs: + const TSTRING testfile = testTWCFG + _T("tripwire.cfg"); + + //Insert the test values into cConfigFile's hashtable: + /* + write_cfgmod.Insert( _T("TWROOT"), testTWROOT); + write_cfgmod.Insert( _T("TWBIN"), testTWBIN); + write_cfgmod.Insert( _T("TWCFG"), testTWCFG); + write_cfgmod.Insert( _T("TWMAN"), testTWMAN); + write_cfgmod.Insert( _T("TWHTML"), testTWHTML); + write_cfgmod.Insert( _T("TWDB"), testTWDB); + write_cfgmod.Insert( _T("TWKEY"), testTWKEY); + write_cfgmod.Insert( _T("TWREPORT"), testTWREPORT); + write_cfgmod.Insert( _T("TWPASSWORD"), testTWPASSWORD); + */ + + //Store these values on disk. + TSTRING configText; + write_cfgmod.WriteString(configText); + cTWUtil::WriteConfigText(testfile.c_str(), configText, false, NULL); + + //Instantiate another cConfigFile object for reading back + //values: + cConfigFile read_cfgmod; + + try + { + cTWUtil::ReadConfigText(testfile.c_str(), configText); + read_cfgmod.ReadString(configText); + } + catch (eError& error) + { + TCERR << (int)error.GetID() << std::endl << error.GetMsg() << std::endl; + ASSERT(false); + } + + //These TSTRINGS will hold info. from .Lookup: + TSTRING lookup1, lookup2; + + read_cfgmod.Lookup( _T("TWROOT"), lookup1); + read_cfgmod.Lookup( _T("TWDB"), lookup2); + d.TraceDetail("First lookup's value: %s \n", lookup1.c_str()); + d.TraceDetail("Second lookup's value: %s \n", lookup2.c_str()); + TEST( lookup1 == testTWROOT ); + TEST( lookup2 == testTWDB ); + + d.TraceDetail("Tests Passed!\n"); +#endif // NOT_BRIANS_TEST +} diff --git a/src/tw/dbdatasource.cpp b/src/tw/dbdatasource.cpp new file mode 100644 index 0000000..753a10a --- /dev/null +++ b/src/tw/dbdatasource.cpp @@ -0,0 +1,403 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// dbdatasource.cpp +// + +#include "stdtw.h" +#include "dbdatasource.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "core/archive.h" +#include "core/serializerimpl.h" +#include "fco/fcopropset.h" +#include "fco/fco.h" +#include "fco/fcodatasourceiter.h" + +// TODO -- get rid of this include somehow! +#include "fco/genreswitcher.h" + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cDbDataSourceIter::cDbDataSourceIter(cHierDatabase* pDb, int genreNum ) +: iFCODataSourceIter (), + mDbIter (pDb), + mFlags (0), + mpErrorBucket (0) +{ + // + // remember the fco creation function... + // TODO -- Note that this couples this file with cGenreSwitcher; perhaps this should take the fco creation + // function instead... + // + if( genreNum == -1 ) + genreNum = cGenreSwitcher::GetInstance()->CurrentGenre(); + mFCOCreateFunc = cGenreSwitcher::GetInstance()->GetFactoryForGenre( (cGenre::Genre)genreNum )->GetCreateFunc(); + +#ifdef _DEBUG + // + // make some assertions about the current genre's name info + // + iFCONameInfo* pNameInfo = cGenreSwitcher::GetInstance()->GetFactoryForGenre( (cGenre::Genre)genreNum )->GetNameInfo(); + ASSERT( pDb->IsCaseSensitive() == pNameInfo->IsCaseSensitive() ); + ASSERT( pDb->GetDelimitingChar() == pNameInfo->GetDelimitingChar() ); +#endif //#ifdef _DEBUG +} + +/////////////////////////////////////////////////////////////////////////////// +// cDbDataSourceIter +/////////////////////////////////////////////////////////////////////////////// +cDbDataSourceIter::cDbDataSourceIter( const cDbDataSourceIter& rhs ) +: mDbIter ( rhs.mDbIter ), + mFCOCreateFunc ( rhs.mFCOCreateFunc ), + mFlags ( rhs.mFlags ), + mpErrorBucket ( rhs.mpErrorBucket ) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// operator= +/////////////////////////////////////////////////////////////////////////////// +cDbDataSourceIter& cDbDataSourceIter::operator=( const cDbDataSourceIter& rhs ) +{ + mDbIter = rhs.mDbIter ; + mFCOCreateFunc = rhs.mFCOCreateFunc ; + mFlags = rhs.mFlags; + mpErrorBucket = rhs.mpErrorBucket; + return (*this); +} + + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cDbDataSourceIter::~cDbDataSourceIter() +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateCopy +/////////////////////////////////////////////////////////////////////////////// +iFCODataSourceIter* cDbDataSourceIter::CreateCopy() const +{ + //TODO -- implement this with a memory pool? + return new cDbDataSourceIter(*this); +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetName +/////////////////////////////////////////////////////////////////////////////// +cFCOName cDbDataSourceIter::GetName() const +{ + ASSERT( ! Done() ); + + cFCOName rtn( mDbIter.GetCwd() ); + rtn.Push( mDbIter.GetName() ); + return rtn; +} + + +/////////////////////////////////////////////////////////////////////////////// +// CreateFCO +// +// note that cHierDatabase::GetData() will throw if we are Done() or the node +// doesn't have data +/////////////////////////////////////////////////////////////////////////////// +iFCO* cDbDataSourceIter::CreateFCO() //throw (eError) +{ + ASSERT( ! Done() ); + // + // ok, first, we will create the new fco... + // + iFCO* pFCO = static_cast( (*mFCOCreateFunc)() ); + pFCO->SetName( GetName() ); + try + { + ASSERT( mDbIter.HasData() ); + int32 length; + int8* pData = mDbIter.GetData(length); + // + // associate a serializer with this memory and read in the property set... + // + cFixedMemArchive arch( pData, length ); + cSerializerImpl ser ( arch, cSerializerImpl::S_READ ); + ser.Init(); + ser.ReadObject( pFCO->GetPropSet() ); + ser.Finit(); + } + catch(...) + { + pFCO->Release(); + throw; + } + + return pFCO; +} + +/////////////////////////////////////////////////////////////////////////////// +// HasFCOData +/////////////////////////////////////////////////////////////////////////////// +bool cDbDataSourceIter::HasFCOData() const +{ + ASSERT( ! Done() ); + if( Done() ) + return false; + + return ( mDbIter.HasData() ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// SeekToFCO +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::SeekToFCO(const cFCOName& name, bool bCreatePeers) //throw(eFCODataSourceIter) +{ + ASSERT( name.GetSize() > 0 ); + cFCOName parentName = name; + parentName.Pop(); + if(! SeekToDirectory( parentName, false ) ) + { + // make myself Done() and return... + // + while( ! Done() ) Next(); + return; + } + // + // note that this is Done() if it fails, so we are good... + // + mDbIter.SeekTo( name.GetShortName() ) ; +} + +/////////////////////////////////////////////////////////////////////////////// +// AddFCO +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::AddFCO( const TSTRING& shortName, const iFCO* pFCO ) //throw (eFCODataSourceIter, eError) +{ + mDbIter.CreateEntry( shortName ); + // + // we are now pointing at the entry we just created, so now let's add the data... + // + SetFCOData( pFCO ); +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveFCO +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::RemoveFCO() //throw (eError) +{ + if( (! Done()) && (! HasFCOData()) ) + { + mDbIter.DeleteEntry(); + } + else + { + // this was called in inappropriate circumastances + ASSERT( false ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveFCOData +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::RemoveFCOData() //throw (eError) +{ + ASSERT( ! Done() ); + ASSERT( HasFCOData() ); + if( HasFCOData() ) + { + mDbIter.RemoveData(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// SetFCOData +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::SetFCOData( const iFCO* pFCO ) //throw (eError) +{ + ASSERT( ! Done() ); + if( Done() ) + { + throw eHierDatabase( _T("Attempt to set FCO data when the iterator is done.") ); + } + // TODO -- assert and throw if the fco's type is not the same as our creation function + // There is no way to do this through the serializable interface, but when there is, + // we should do the above assertion. + // + // if data already exists here, we first remove it; + // + if( mDbIter.HasData() ) + { + mDbIter.RemoveData(); + } + // + // write the fco's property set to a memory archive... + // + // TODO -- does this need to be static? + static cMemoryArchive arch; + arch.Seek ( 0, cBidirArchive::BEGINNING ); + cSerializerImpl ser (arch, cSerializerImpl::S_WRITE); + ser.Init(); + ser.WriteObject ( pFCO->GetPropSet() ); + ser.Finit(); + // + // write this to the archive... + // + mDbIter.SetData( arch.GetMemory(), arch.CurrentPos() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AddChildArray +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::AddChildArray() //throw (eError) +{ + ASSERT( ! Done() ); + ASSERT( ! CanDescend() ); + + mDbIter.CreateChildArray(); +} + +/////////////////////////////////////////////////////////////////////////////// +// RemoveChildArray +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::RemoveChildArray() //throw (eError) +{ + //NOTE -- the hier db iter does all of the proper asserting... + // + mDbIter.DeleteChildArray(); +} + +/////////////////////////////////////////////////////////////////////////////// +// CreatePath +/////////////////////////////////////////////////////////////////////////////// +void cDbDataSourceIter::CreatePath( const cFCOName& name ) //throw (eError) +{ + ASSERT( name.GetSize() > 0 ); + + cFCOName parentName = name; + parentName.Pop(); + SeekToDirectory( parentName, true ); + if( ! mDbIter.SeekTo( name.GetShortName() ) ) + { + mDbIter.CreateEntry( name.GetShortName() ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// SeekToDirectory +/////////////////////////////////////////////////////////////////////////////// +bool cDbDataSourceIter::SeekToDirectory( const cFCOName& parentName, bool bCreate ) +{ + cDebug d( "cDbDataSourceIter::SeekToDirectory" ); + // + // the first task is to ascend until we are in a directory that we can descend into to + // reach parentName... + // + cFCOName curParent = GetParentName(); + d.TraceDebug( _T("Entering... Seeking to %s (cwd = %s)\n"), parentName.AsString().c_str(), curParent.AsString().c_str() ); + int ascendCount ; + switch( curParent.GetRelationship( parentName ) ) + { + case cFCOName::REL_BELOW: + // + // we must ascend... + // + ascendCount = curParent.GetSize() - parentName.GetSize(); + d.TraceDetail( _T("\tAscending %d times...\n"), ascendCount ); + ASSERT( ascendCount > 0 ); + for( ; ascendCount > 0; ascendCount-- ) + Ascend(); + break; + case cFCOName::REL_ABOVE: + // + // we are above the needed directory; nothing else to do here... + // + d.TraceDetail( _T("\tAbove; not ascending...\n") ); + break; + case cFCOName::REL_EQUAL: + // + // we need to do nothing else here... + // + d.TraceDetail( _T("\tEqual; doing nothing...\n") ); + SeekBegin(); + return true; + case cFCOName::REL_UNRELATED: + // + // we have to go all the way to the root... + // + d.TraceDetail( _T("\tUnrelated; seeking to root...\n") ); + SeekToRoot(); + break; + default: + // unreachable + ASSERT( false ); + return false; + } + + curParent = GetParentName(); + if( parentName.GetSize() == curParent.GetSize() ) + return true; + // + // now we will descend to the parent directory we are interested in... + // + cFCOName::iterator i(parentName); + i.SeekTo( curParent.GetSize() ); + for(; (! i.Done()); i.Next() ) + { + if( ! mDbIter.SeekTo( i.GetName() ) ) + { + // this needs to be created! + if( bCreate ) + mDbIter.CreateEntry( i.GetName() ); + else + return false; + } + // + // create the child array and descend + // + if( ! mDbIter.CanDescend() ) + { + if( bCreate ) + mDbIter.CreateChildArray(); + else + return false; + } + mDbIter.Descend(); + } + return true; +} + + diff --git a/src/tw/dbdatasource.h b/src/tw/dbdatasource.h new file mode 100644 index 0000000..b3d429a --- /dev/null +++ b/src/tw/dbdatasource.h @@ -0,0 +1,282 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// dbdatasource.h +// +#ifndef __DBDATASOURCE_H +#define __DBDATASOURCE_H + +#ifndef __FCODATASOURCEITER_H +#include "fco/fcodatasourceiter.h" +#endif +#ifndef __HIERDATABASE_H +#include "db/hierdatabase.h" +#endif +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" +#endif + +class cDbDataSourceIter : public iFCODataSourceIter +{ +public: + cDbDataSourceIter( cHierDatabase* pDb, int genreNum = -1) ; //throw (eError) + // this ctor asserts that the case-sensitiveness and delimiting char match that of the passed in genre... + // if -1 is passed for the genre num, then the current genre is used. + + cDbDataSourceIter ( const cDbDataSourceIter& rhs ); + cDbDataSourceIter& operator=( const cDbDataSourceIter& rhs ); + + + virtual ~cDbDataSourceIter(); + + virtual iFCODataSourceIter* CreateCopy() const ; + + virtual const TCHAR* GetShortName() const ; + virtual cFCOName GetName() const ; + virtual cFCOName GetParentName() const ; + + virtual bool AtRoot() const ; //throw (eError) + virtual bool CanDescend() const ; //throw (eError) + virtual void Descend() ; //throw (eError) + virtual void Ascend() ; //throw (eError) + + virtual void SeekBegin() ; + virtual bool Done() const ; + virtual void Next() ; + virtual bool SeekTo( const TCHAR* shortName ); + virtual bool IsCaseSensitive() const; + + virtual iFCO* CreateFCO() ; //throw (eError) + virtual void SetErrorBucket( cErrorBucket* pBucket ); + + /////////////////////////////////////////////// + // This stuff is in this derived class _only_ + void SeekToRoot(); //throw( eError ) + // seeks to the root of the database + virtual void AddFCO( const TSTRING& shortName, const iFCO* pFCO ) ; //throw (eFCODataSourceIter, eError) + // adds the fco to the current directory; this throws an exception if + // the insert fails or an fco already named the same exists in the directory. After the insertion, + // the iterator points at the new node. + virtual void RemoveFCO() ; //throw (eError) + // removes the current fco; iterator then points at the next object or done() is true if it is at the end. + virtual void SetFCOData( const iFCO* pFCO ) ; //throw (eError) + // sets the data associated with the current FCO. This method pays no attention to the FCO's name. (maybe I + // should assert?) + virtual void RemoveFCOData() ; //throw (eError) + // removes the fco data associated with the current fco. This asserts the iterator is not done and contains + // data. + bool HasFCOData() const; + // this returns true if the current node contains fco data. If this returns false, then it is not + // legal to call CreateFCO() + void CreatePath( const cFCOName& name ) ; //throw (eError) + // a convenience method that creates the named path (or any part that is currently not created) + // the iterator ends up with the named path as the current item (ie -- it will be returned from + // GetName()) + void AddChildArray() ; //throw (eError) + // this adds a child array to the current FCO. This asserts that one does not currently exist and + // that Done() is not true + void RemoveChildArray() ; //throw (eError) + //this asserts that Done() is not true, and the child array contains nothing. + bool CanRemoveChildArray(); //throw (eError) + // returns true if the child array is empty, and can thus be removed with RemoveChildArray() + void Refresh(); // throw (eError) + + // + /////////////////////////////////////////////// + virtual void SeekToFCO(const cFCOName& name, bool bCreatePeers = true) ; //throw(eFCODataSourceIter) + // NOTE -- this class ignores bCreatePeers + + virtual int GetIterFlags() const; + virtual void SetIterFlags(int i); + +private: + // + // helper methods + // + bool SeekToDirectory( const cFCOName& parentName, bool bCreate = false ); + // seeks the iterator to the named directory. This method attempts to take the most direct route possible, + // seeking from the current working directory instead of seeking to the root and then descending to the + // named directory. When this operation returns, it is positioned at the first element in the named directory + // unless false is returned, in which case the iterator is positioned at an undefined location. If bCreate + // is true, the directory is created if it does not currently exist. + + + + cHierDatabase::iterator mDbIter; + iSerRefCountObj::CreateFunc mFCOCreateFunc; // points to the function that creates the fcos we return + uint32 mFlags; // flags used for iteration + cErrorBucket* mpErrorBucket; +}; + +//############################################################################# +// inline implementation +//############################################################################# + +inline void cDbDataSourceIter::Refresh() +{ + mDbIter.Refresh(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekTo +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::SeekTo( const TCHAR* shortName ) +{ + return mDbIter.SeekTo(shortName); +} + + +/////////////////////////////////////////////////////////////////////////////// +// SeekToRoot +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::SeekToRoot() +{ + mDbIter.SeekToRoot(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetParentName +/////////////////////////////////////////////////////////////////////////////// +inline cFCOName cDbDataSourceIter::GetParentName() const +{ + cFCOName rtn( mDbIter.GetCwd() ); + return rtn; +} + +/////////////////////////////////////////////////////////////////////////////// +// AtRoot +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::AtRoot() const //throw (eError) +{ + return ( mDbIter.AtRoot() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// CanDescend +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::CanDescend() const //throw (eError) +{ + return ( mDbIter.CanDescend() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Descend +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::Descend() //throw (eError) +{ + mDbIter.Descend(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Ascend +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::Ascend() //throw (eError) +{ + mDbIter.Ascend(); +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekBegin +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::SeekBegin() +{ + mDbIter.SeekBegin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Done +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::Done() const +{ + return ( mDbIter.Done() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Next +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::Next() +{ + mDbIter.Next(); +} + +/////////////////////////////////////////////////////////////////////////////// +// IsCaseSensitive +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::IsCaseSensitive() const +{ + return mDbIter.IsCaseSensitive(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetShortName +/////////////////////////////////////////////////////////////////////////////// +inline const TCHAR* cDbDataSourceIter::GetShortName() const +{ + ASSERT( ! Done() ); + + return mDbIter.GetName(); +} + +/////////////////////////////////////////////////////////////////////////////// +// CanRemoveChildArray +/////////////////////////////////////////////////////////////////////////////// +inline bool cDbDataSourceIter::CanRemoveChildArray() +{ + return ( mDbIter.ChildArrayEmpty() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetIterFlags +/////////////////////////////////////////////////////////////////////////////// +inline int cDbDataSourceIter::GetIterFlags() const +{ + return mFlags; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetIterFlags +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::SetIterFlags( int i ) +{ + mFlags = i; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetIterFlags +/////////////////////////////////////////////////////////////////////////////// +inline void cDbDataSourceIter::SetErrorBucket( cErrorBucket* pBucket ) +{ + mpErrorBucket = pBucket; +} + +#endif + diff --git a/src/tw/dbdatasource_t.cpp b/src/tw/dbdatasource_t.cpp new file mode 100644 index 0000000..0ed0af0 --- /dev/null +++ b/src/tw/dbdatasource_t.cpp @@ -0,0 +1,300 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// dbdatasource_t.cpp +#include "stdtw.h" +#include "dbdatasource.h" +#include "db/hierdatabase.h" +#include "core/fsservices.h" +#include "core/debug.h" +#include "core/error.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" +#include "fco/fco.h" + +static void GetNoun( TSTRING& noun ) +{ + static TSTRING prevNoun; + TCIN >> noun; + if( noun.compare( _T("!$") ) == 0 ) + { + noun = prevNoun; + } + prevNoun = noun; +} + +// +// TODO -- implement this with the prop displayer as well! +// +static void PrintFCO( const iFCO* pFCO ) +{ + TCOUT.setf(std::ios::left); + + TCOUT << "------- " << pFCO->GetName().AsString() << " -------" << std::endl; + // + // iterate over all of the properties + // + const iFCOPropSet* pPropSet = pFCO->GetPropSet(); + cFCOPropVector v = pPropSet->GetValidVector(); + for( int i=0; i < pPropSet->GetNumProps(); i++ ) + { + if( v.ContainsItem( i ) ) + { + TCOUT << "["; + TCOUT.width(2); + TCOUT << i << "]" ; + TCOUT.width(25); + TCOUT << pPropSet->GetPropName(i); + TCOUT.width(0); + TCOUT << pPropSet->GetPropAt( i )->AsString() << std::endl; + } + } + TCOUT << "--------------------------------------------" << std::endl; +} + + +void TestDbDataSource() +{ + cDebug d("TestDbDataSource"); + cHierDatabase db; + + const TSTRING dbName = _T("c:/tmp/tw.db"); + + try + { + // TODO -- get the case sensitiveness and delimiting char out of the factory instead of iFSServices + // + TCOUT << _T("Opening database ") << dbName << std::endl; + db.Open( dbName, 5, false ); + cDbDataSourceIter iter( &db ); + + //////////////////////////// + // the main event loop... + //////////////////////////// + while( true ) + { + TSTRING verb, noun; + TCOUT << _T(">>"); + TCIN >> verb; + // + // ok, now we switch on the command... + // + //----------------------------------------------------------------- + // quit + //----------------------------------------------------------------- + if( verb.compare( _T("quit") ) == 0 ) + { + // the quit command... + break; + } + //----------------------------------------------------------------- + // print + //----------------------------------------------------------------- + if( verb.compare( _T("print") ) == 0 ) + { + GetNoun(noun); + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.HasFCOData() ) + { + iFCO* pFCO = iter.CreateFCO(); + PrintFCO( pFCO ); + pFCO->Release(); + } + else + { + TCOUT << "Object has no data associated with it." << std::endl; + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // mkdir + //----------------------------------------------------------------- + else if( verb.compare( _T("mkdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making a child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + iter.AddChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // mk + //----------------------------------------------------------------- + else if( verb.compare( _T("mk") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + TCOUT << "Error: object already exists!" << std::endl; + } + else + { + iter.AddFCO( noun, 0 ); // add a null fco for now + } + } + //----------------------------------------------------------------- + // rmdir + //----------------------------------------------------------------- + // TODO -- still needs to be implemented in the iterator class! + // + /* + else if( verb.compare( _T("rmdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing the child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + //TODO -- check that it has an empty child + iter.DeleteChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + */ + //----------------------------------------------------------------- + // rm + //----------------------------------------------------------------- + else if( verb.compare( _T("rm") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Can't delete object; it still has children." << std::endl; + } + else + { + iter.RemoveFCO(); + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwd + //----------------------------------------------------------------- + else if( verb.compare( _T("pwd") ) == 0 ) + { + TCOUT << iter.GetParentName().AsString() << std::endl; + } + //----------------------------------------------------------------- + // ls + //----------------------------------------------------------------- + else if( verb.compare( _T("ls") ) == 0 ) + { + int cnt = 0; + for( iter.SeekBegin(); ! iter.Done(); iter.Next(), cnt++ ) + { + TCOUT << "[" << cnt ; + if( iter.CanDescend() ) + { + TCOUT << "]*\t" ; + } + else + { + TCOUT << "]\t" ; + } + TCOUT << iter.GetShortName() << std::endl; + } + } + //----------------------------------------------------------------- + // cd + //----------------------------------------------------------------- + else if( verb.compare( _T("cd") ) == 0 ) + { + GetNoun(noun); + if( noun.compare( _T("..") ) == 0 ) + { + if( iter.AtRoot() ) + { + TCOUT << "Can't ascend above root." << std::endl; + } + else + { + TCOUT << "Ascending..." << std::endl; + iter.Ascend(); + } + } + else + { + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Descending into " << noun << std::endl; + iter.Descend(); + } + else + { + TCOUT << noun << " has no children; can't descend." << std::endl; + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + } + + // make sure the file is still valid... + // +#ifdef _BLOCKFILE_DEBUG + db.AssertAllBlocksValid() ; +#endif + } + + TCOUT << "Exiting..." << std::endl; + + + } + catch( eError& e ) + { + d.TraceError("*** Caught error: %d %s\n", e.GetID(), e.GetMsg().c_str() ); + } +} diff --git a/src/tw/dbdebug.cpp b/src/tw/dbdebug.cpp new file mode 100644 index 0000000..869d179 --- /dev/null +++ b/src/tw/dbdebug.cpp @@ -0,0 +1,824 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +//dbdebug.cpp +// + +#include "stdtw.h" + +#include "dbdebug.h" +#include "db/hierdatabase.h" +#include "db/hierdbnode.h" +#include "db/blockrecordarray.h" +#include "db/blockfile.h" +#include "dbdatasource.h" +#include "fcodatabasefile.h" +#include "db/blockrecordfile.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" + +#include "core/error.h" +#include "core/errorbucketimpl.h" +#include "core/debug.h" +#include "fco/genreswitcher.h" + +#include "fco/fcopropdisplayer.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" + +#include +#include +#include +#include +#include "core/tchar.h" +#include "core/types.h" + +////////////////////////////////////////////////////////////////////////////////////////////////// +// UTILITY METHODS +////////////////////////////////////////////////////////////////////////////////////////////////// +// +static void util_PrintFCO(const iFCO* pFCO, iFCOPropDisplayer * pPropDisplayer); +static void util_InitBlockArray( cBlockRecordArray& block ); +static void util_MapHierRoot( std::map< std::pair< int, int>, int > dbMap ); + +////////////////////////////////////////////////////////////////////////////////////////////////// +// Insulated implementation: +////////////////////////////////////////////////////////////////////////////////////////////////// +struct cDbDebug_i +{ + cDbDebug_i() {}; + ~cDbDebug_i() {}; + + typedef std::map< std::pair, int > hierDbMap; + // This is the data structure that we will use to match the information stored in a quantum database + // with its hierarchical representation! For now, it will hold the tuples representing + // valid offsets in each block (referenced by a block number). The bool value will be set to false + // on the first run, and then flipped to true for each entry that is found while traversing the + // hierarchical database. + typedef std::list< std::pair< int, int> > AddressList; + + hierDbMap mDbMap; // The map itself. + AddressList mlMissingFromBlockFile; // A list for keeping track of nodes found in the hierarchy, but not the blockfile + AddressList mlMissingFromHierarchy; // The opposite case. +}; + +cDbDebug::cDbDebug() +{ + mpData = new cDbDebug_i(); +} + +cDbDebug::~cDbDebug() +{ + delete mpData; +} + + +/////////////////////////////////////////////////////////////////////////////// +// util_InitBlockArray +/////////////////////////////////////////////////////////////////////////////// +static void util_InitBlockArray( cBlockRecordArray& block ) +{ + if( ! block.Initialized() ) + { + block.InitForExistingBlock(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// util_MapHierRoot : Map the Root and RootArray in the HierDatabase: +/////////////////////////////////////////////////////////////////////////////// +static void util_MapHierRoot( std::map< std::pair< int, int>, int >* dbMap ) +{ + cDbDebug_i::hierDbMap::iterator i = dbMap->find( std::pair ( 0, 0 ) ); + //dbMap->insert( cDbDebug_i::hierDbMap::value_type( std::pair< int, int > ( 0, 0 ), 1 ) ); + // + // This insert statement should work to change the value, but it doesn't ???? + (*i).second = 1; + + i = dbMap->find( std::pair ( 0, 1 ) ); + (*i).second = 1; + + i = dbMap->find( std::pair ( 0, 2 ) ); + (*i).second = 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// DisplayDbMap -- Displays the entire map. +/////////////////////////////////////////////////////////////////////////////// +void cDbDebug::DisplayDbMap() +{ + int loop_count = 0; + + for(cDbDebug_i::hierDbMap::iterator i = cDbDebug::mpData->mDbMap.begin(); i!= cDbDebug::mpData->mDbMap.end(); ++i, ++loop_count) + { + TCOUT.width(6); + TCOUT<< (*i).first.first << _T(",") << (*i).first.second<<_T(" "); + TCOUT<<_T("(")<< (*i).second<<_T(")"); + if( (loop_count % 5) == 0 ) + TCOUT<< std::endl; + } + TCOUT<mDbMap); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// Execute : +// Drives the DebugDb mode of tripwire, which will only be used for internal use. +////////////////////////////////////////////////////////////////////////////////////////////////////// +void cDbDebug::Execute( cFCODatabaseFileIter& dbIter, const TSTRING& dbFile ) +{ + + cDebug d("cDebugDb::Execute"); + cDbDebug DbDebug; + // + //A derived class with extra methods for obtaining blockfile information. + cDebugHierDb* db; + // + // Cast the database object that we have inherited from the "common" command line + // information to a cDebugHierDb. This will expose all the information that we + // need to debug the database. + // + db = static_cast(&(dbIter.GetDb())); + + try + { + cDebugHierDbIter pIter( db ); + + // + //First, map the state of the underlying quantyum database. Store this info. in + //the hierDbMap. + // + DbDebug.MapQuantumDatabase( *db ); + + //DbDebug.DisplayDbMap(); //TODO : get rid of these display calls. + + // + // Uncomment ManipDb() to allow manipulation of the database + // This may be handy if one does not want to do a full update... + //DbDebug.ManipDb( dbIter ); + + // Next, traverse the hierarchical overlay and "tag" all entries in the map that + // we see: + ASSERT( pIter.AtRoot() ); + // + // check to make sure we are at the root of the hierarchy, if so, map the root + // before calling the recursive traversal function. + // + util_MapHierRoot( DbDebug.GetHierDbMap() ); + + DbDebug.TraverseHierarchy( pIter /*, db*/ ); + + //DbDebug.DisplayDbMap(); //TODO: get rid of these display calls. + // + // Finally, iterate over the map and see if there is any data that the hierarchy + // does not account for: + // + DbDebug.CongruencyTest(); + // + // Output the results + // + DbDebug.OutputResults(); + + }//try + + catch( eError& e ) + { + cErrorReporter::PrintErrorMsg( e ); + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +// MapQuantumDatabase -- +// +// Our objective is to map all the information that the database is currently storing. It +// may be necessary to do some hacking about with the database object in order to expose +// all the information necessary to accomplish this. +// +// Addition: 2/15/99: We want to print out statistics on the current state of the block +// file, so let's do it here ( since we're traversing it to map the addresses, anyway ). +////////////////////////////////////////////////////////////////////////////////////////////// +void cDbDebug::MapQuantumDatabase( cDebugHierDb& db ) +{ + //mirroring the implementation in blockrecordfile.h: + typedef std::vector BlockArray; + + //Using the two added methods to gain access to the low-level implementation of the + //quantum database. + BlockArray* pBlkArray = db.myGetBlockArray(); + + // Print some statistics on the blockfile if we're in debug mode: +#ifdef _BLOCKFILE_DEBUG + db.myGetBlockFile()->TraceContents(); +#endif + // Prints as much information about the current state of the block file as can be + // assessed. + + // time to iterate over the database: + std::vector< cBlockRecordArray >::iterator i; + int count = 0; + + for( i = (*pBlkArray).begin(); i != (*pBlkArray).end(); ++i, ++count ) + { + util_InitBlockArray( *i ); + //This is necessary to make sure that each block is initialized as we iterate + //over the block array. + // + // Print out statistics on this block, if we're in debug mode: +#ifdef _BLOCKFILE_DEBUG + i->TraceContents(); +#endif + + + //Search through all the indexes and determine which of them references valid + //information. Store these pairs ( the first int being the value of + //count.... + for( int j = 0; j <= i->GetNumItems(); ++j ) + { + if( i->IsItemValid( j ) ) + { + // + // We found a valid node in the database, so store it in the map. + // + mpData->mDbMap.insert( cDbDebug_i::hierDbMap::value_type( std::pair (count, j) , 0 )); + } + // if not, just don't store it. The index is no longer valid. + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +// TraverseHierarchy -- +// +// A recursive function for traversing a hierarchical database, accounting for all the data +// structures that make up the object. Looks at data addresses as well as structures that are +// necessary to maintain the hierarchy ( namely cHierArrayInfo records ). +//////////////////////////////////////////////////////////////////////////////////////////////// +void cDbDebug::TraverseHierarchy( cDebugHierDbIter pIter) +{ + if( ! pIter.CanDescend() ) + return; //Done with this call. + + pIter.Descend(); + // + //Descend once from the root, into the first child set. Also, descend once for each recursive call. + // + + for( pIter.SeekBegin(); !pIter.Done(); pIter.Next() ) + { + //Try to match the parent's address in the database. + if( !pIter.Done() ) + { + if( pIter.myGetEntryArrayIt() == pIter.myGetEntryArray().begin() ) + //We're dealing with a cHierArrayInfo object, so treat it differently. + { + // + // Let's map the parent address, and the array address, so we account for all the data structures + // that make up this particular node. + // + MapHierDbNodes( mpData->mDbMap, std::pair(pIter.myGetArrayInfo().mParent.mBlockNum, pIter.myGetArrayInfo().mParent.mIndex), pIter ); + // and the array... + MapHierDbNodes( mpData->mDbMap, std::pair(pIter.myGetArrayInfo().mArray.mBlockNum, pIter.myGetArrayInfo().mArray.mIndex), pIter ); + } + else + //This is a regular cHierEntry, so look at the Data and Child (if it exists ). + { + + cDebugHierDbIter::EntryArray::iterator lEntryArrayIt = pIter.myGetEntryArrayIt(); + + MapHierDbNodes( mpData->mDbMap, std::pair(lEntryArrayIt->mData.mBlockNum, lEntryArrayIt->mData.mIndex), pIter ); + + --lEntryArrayIt; + // Get the address of this node by examining the previous next pointer in the entry list. + // + + // + // Map the next peer entry in the list. TODO: This may very well be overkill... if so, lose this call to MapHierDbNodes. + // + MapHierDbNodes( mpData->mDbMap, std::pair(lEntryArrayIt->mNext.mBlockNum, lEntryArrayIt->mNext.mIndex), pIter ); + // + // We also want to map the address of the child array, if non-null. + // + if( lEntryArrayIt->mChild.mBlockNum != -1 ) + MapHierDbNodes( mpData->mDbMap, std::pair(lEntryArrayIt->mChild.mBlockNum, lEntryArrayIt->mChild.mIndex), pIter ); + // + // Finally, map the address of the data. + // + MapHierDbNodes( mpData->mDbMap, std::pair(lEntryArrayIt->mData.mBlockNum, lEntryArrayIt->mData.mIndex), pIter ); + } + + }//if + // + // Check to see if this particular node has a child array. If so, make recursive call. + // + if( pIter.CanDescend() ) + { + //This node has children, call myself + TraverseHierarchy( pIter ); + } + }//for +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MapHierDbNodes -- +// +// Maps a given address in the hierarchy. This function looks up the address in the map and flips an integer flag +// to record the event. If the address is not found, it is placed in a list of addresses for error output. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void cDbDebug::MapHierDbNodes( std::map< std::pair< int, int > , int >& dbMap, std::pair address, cDebugHierDbIter& pIter ) +{ + cDbDebug_i::hierDbMap::iterator i = dbMap.find( std::pair< int, int> (address.first, address.second) ); + + if( i != dbMap.end() ) + { + (*i).second = 1; + //Flip the integer flag to 1, since we've found the address in the hierarchy. + } + else + mpData->mlMissingFromBlockFile.push_back( std::pair (address.first, address.second)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// CongruencyTest -- +// +// Iterate over the map and see if there are any entries that haven't been tagged by our +// hierarchy traversal. If there are, push the offending addresses onto the address list. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void cDbDebug::CongruencyTest( void ) +{ + cDbDebug_i::hierDbMap::iterator i = mpData->mDbMap.begin(); + for( ; i != mpData->mDbMap.end(); ++i ) + { + if ( (*i).second != 1 ) + { + //We've found something in the blockfile map that is not accounted for by the + //hierarchy. Add this address to the appropriate list. + //TCOUT<< (*i).first.first << _T(",") << (*i).first.second << std::endl; + //TCOUT<< (*i).second <mlMissingFromHierarchy.push_back( std::pair< int, int> ( (*i).first.first, (*i).first.second ) ); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OutputResults -- +// +// Output the results of the congruency test. Print information contained in the two +// "error lists" if they have entries. +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void cDbDebug::OutputResults( void ) +{ + TCOUT<< _T("\nResults of Blockfile / Hierarchy congruency tests: \n") << std::endl; + + // Check to see if our error lists are empty. If so, output a message that indicates + // that the two databases checked clean. + if( mpData->mlMissingFromHierarchy.empty() && mpData->mlMissingFromBlockFile.empty() ) + TCOUT<< _T("The database representations match!\n") << std::endl; + else + { + // Check to see if there was anything in the hierarchy that was not accounted for by the + // blockfile (quantum database). + if( !mpData->mlMissingFromBlockFile.empty() ) + { + TCOUT<< _T(" Objects (referenced by address) found in the hierarchy that were not\n"); + TCOUT<< _T(" accounted for by the underlying quantum database: \n"); + + cDbDebug_i::AddressList::iterator i = mpData->mlMissingFromBlockFile.begin(); + for( ; i != mpData->mlMissingFromBlockFile.end(); ++i ) + TCOUT << _T("(") << (*i).first << _T(",") << (*i).second << _T(")") << std::endl; + } + else + TCOUT<< _T(" All objects in Blockfile accounted for!\n"); + + //check to see if there was anything in the blockfile that was not accounted for by the + // hierarchy: + if ( !mpData->mlMissingFromHierarchy.empty() ) + { + TCOUT<< _T(" Database information (referenced by a address)\n"); + TCOUT<< _T(" not accounted for by the hierarchy :\n"); + + cDbDebug_i::AddressList::iterator i = mpData->mlMissingFromHierarchy.begin(); + for( ; i != mpData->mlMissingFromHierarchy.end(); ++i ) + TCOUT << _T("(") << (*i).first << _T(",") << (*i).second << _T(")") << std::endl; + } + else + TCOUT<<_T("All objects in Hierarchy accounted for!\n"); + }//else +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Begin code for manipulating Database -- This is just a straight port from the DbExplore code. It's presence is +// purely for convenience, and for debugging this class. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static inline bool IsSpace( TCHAR c ) +{ + return ( (c == _T(' ')) || (c == _T('\t')) || (c == _T('\r')) || (c == _T('\n')) || (c == _T('\0')) ); +} + +static inline bool IsEnd( TCHAR c ) +{ + return ( (c == _T('\0')) ); +} + +/* +/////////////////////////////////////////////////////////////////////////////// +// util_PrintFCO +/////////////////////////////////////////////////////////////////////////////// +static void util_PrintFCO( const iFCO* pFCO, const iFCOPropDisplayer* pDisplayer ) +{ + TCOUT.setf(std::ios::left); + + TCOUT << "------- " + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pFCO->GetName() ) + << " -------" + << std::endl; + // + // iterate over all of the properties + // + const iFCOPropSet* pPropSet = pFCO->GetPropSet(); + cFCOPropVector v = pPropSet->GetValidVector(); + for( int i=0; i < pPropSet->GetNumProps(); i++ ) + { + if( v.ContainsItem( i ) ) + { + TCOUT << "["; + TCOUT.width(2); + TCOUT << i << "]" ; + TCOUT.width(25); + TCOUT << pPropSet->GetPropName(i); + TCOUT.width(0); + TCOUT << pDisplayer->PropAsString( pFCO, i ) << std::endl; + } + } + TCOUT << "--------------------------------------------" << std::endl; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetNoun +// note -- you can only call this once after the verb (it eats the rest +// of the line!) +/////////////////////////////////////////////////////////////////////////////// +static void GetNoun( TSTRING& noun ) +{ + static TSTRING prevNoun; + TCHAR buf[1024]; + + TCIN.getline( buf, 1024 ); + // + // find the end of the noun... + // + TCHAR* pStart = buf; + TCHAR* end = &buf[1023]; + while( IsSpace(*pStart) && (! IsEnd(*pStart)) && (pStart < end) ) + pStart++; + + if( IsEnd( *pStart ) || (pStart >= end) ) + { + // no noun! + noun = _T(""); + return; + } + TCHAR* pCur = pStart; + bool bQuote = false; + if( *pCur == _T('\"') ) + { + bQuote = true; + pCur++; + pStart++; + } + while( pCur < end ) + { + if( (! bQuote) && IsSpace(*pCur) ) + break; + + if( *pCur == _T('\"') && bQuote) + break; + + pCur++; + } + noun.assign(pStart, (pCur - pStart)); + + if( noun.compare( _T("!$") ) == 0 ) + { + noun = prevNoun; + } + prevNoun = noun; +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekTo -- seeks to the named noun; this takes care of interpriting special +// nouns. If the seek fails, then Done() is true and false is returned. +// If noun is a special character, then it is altered to what it mapped to. +/////////////////////////////////////////////////////////////////////////////// +static bool SeekTo(cDbDataSourceIter* pIter, TSTRING& noun ) +{ + if( noun[0] == _T('*') ) + { + // interprite the rest of the string as a number index to seek to... + int index = _ttoi( &noun[1] ); + if( index < 0 ) + return false; + pIter->SeekBegin(); + for( int i=0; ((i < index) && (! pIter->Done())); i++, pIter->Next() ) + { + + } + if( pIter->Done() ) + return false; + noun = pIter->GetShortName(); + return true; + } + else + return ( pIter->SeekTo( noun.c_str() ) ); +} + +void cDbDebug::ManipDb( cFCODatabaseFileIter& dbIter ) +{ + cDbDataSourceIter* pIter = new cDbDataSourceIter( &dbIter.GetDb(), dbIter.GetGenre() ); + const iFCOPropDisplayer* pDisplayer = dbIter.GetGenreHeader().GetPropDisplayer(); + + //////////////////////////// + // the main event loop... + //////////////////////////// + while( true ) + { + TSTRING verb, noun; + TCOUT << _T(">>"); + TCIN >> verb; + // + // ok, now we switch on the command... + // + //----------------------------------------------------------------- + // quit + //----------------------------------------------------------------- + if( verb.compare( _T("quit") ) == 0 ) + { + // the quit command... + break; + } + //----------------------------------------------------------------- + // print + //----------------------------------------------------------------- + if( verb.compare( _T("print") ) == 0 ) + { + GetNoun(noun); + if( SeekTo( pIter, noun ) ) + { + if( pIter->HasFCOData() ) + { + iFCO* pFCO = pIter->CreateFCO(); + util_PrintFCO( pFCO, pDisplayer ); + pFCO->Release(); + } + else + { + TCOUT << "Object has no data associated with it." << std::endl; + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwd + //----------------------------------------------------------------- + else if( verb.compare( _T("pwd") ) == 0 ) + { + TCOUT << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pIter->GetParentName() ) << std::endl; + } + //----------------------------------------------------------------- + // ls + //----------------------------------------------------------------- + else if( verb.compare( _T("ls") ) == 0 ) + { + int cnt = 0; + for( pIter->SeekBegin(); ! pIter->Done(); pIter->Next(), cnt++ ) + { + TCOUT << "[" << cnt ; + if( pIter->CanDescend() ) + { + TCOUT << "]*\t" ; + } + else + { + TCOUT << "]\t" ; + } + TCOUT << pIter->GetShortName() << std::endl; + } + } + //----------------------------------------------------------------- + // cd + //----------------------------------------------------------------- + else if( verb.compare( _T("cd") ) == 0 ) + { + GetNoun(noun); + if( noun.compare( _T("..") ) == 0 ) + { + if( pIter->AtRoot() ) + { + TCOUT << "Can't ascend above root." << std::endl; + } + else + { + TCOUT << "Ascending..." << std::endl; + pIter->Ascend(); + } + } + else + { + if( SeekTo( pIter, noun ) ) + { + if( pIter->CanDescend() ) + { + TCOUT << "Descending into " << noun << std::endl; + pIter->Descend(); + } + else + { + TCOUT << noun << " has no children; can't descend." << std::endl; + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + } + //----------------------------------------------------------------- + // cg + //----------------------------------------------------------------- + else if( verb.compare( _T("cg") ) == 0 ) + { + GetNoun(noun); + + cGenre::Genre newGenre = cGenreSwitcher::GetInstance()->StringToGenre( noun.c_str() ); + + if (newGenre != cGenre::GENRE_INVALID) + { + dbIter.SeekToGenre( newGenre ); + if( !dbIter.Done() ) + { + TCOUT << _T("Changing to Genre ") << noun << std::endl; + // + // create a new db iter for the new genre (db iters can only be + // assocaited with a single genre :-( ) + // + delete pIter; + pIter = new cDbDataSourceIter( &dbIter.GetDb(), newGenre ); + } + else + { + TCOUT << _T("Unable to find Genre ") << noun << std::endl; + } + } + else + { + TCOUT << _T("Invalid Genre ") << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwg + //----------------------------------------------------------------- + else if( verb.compare( _T("pwg") ) == 0 ) + { + TCOUT << _T("Current Genre: ") << cGenreSwitcher::GetInstance()->GenreToString( (cGenre::Genre)dbIter.GetGenre(), true ) << std::endl; + } + + //----------------------------------------------------------------- + // mkdir + //----------------------------------------------------------------- + else if( verb.compare( _T("mkdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making a child of " << noun << std::endl; + if( pIter->SeekTo( noun.c_str() ) ) + { + pIter->AddChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // mk + //----------------------------------------------------------------- + else if( verb.compare( _T("mk") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making object " << noun << std::endl; + if( pIter->SeekTo( noun.c_str() ) ) + { + TCOUT << "Error: object already exists!" << std::endl; + } + else + { + pIter->AddFCO( noun, 0 ); // add a null fco for now + } + } + //----------------------------------------------------------------- + // rmdir + //----------------------------------------------------------------- + // TODO -- still needs to be implemented in the pIterator class! + // + else if( verb.compare( _T("rmdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing the child of " << noun << std::endl; + if( pIter->SeekTo( noun.c_str() ) ) + { + //TODO -- check that it has an empty child + pIter->RemoveChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // rm + //----------------------------------------------------------------- + else if( verb.compare( _T("rm") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing object " << noun << std::endl; + if( pIter->SeekTo( noun.c_str() ) ) + { + if( pIter->CanDescend() ) + { + TCOUT << "Can't delete object; it still has children." << std::endl; + } + else + { + pIter->RemoveFCO(); + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // help + //----------------------------------------------------------------- + if( verb.compare( _T("help") ) == 0 ) + { + TCOUT << _T("Commands: ") << std::endl + << _T(" cd ") << std::endl + << _T(" pwd ") << std::endl + << _T(" ls ") << std::endl + << _T(" print ") << std::endl + << _T(" cg (FS | NTFS | NTREG)")<< std::endl + << _T(" pwg") << std::endl + << _T(" quit") << std::endl; + } + + // make sure the file is still valid... + // + } + + delete pIter; + TCOUT << "Exiting..." << std::endl; +} +*/ diff --git a/src/tw/dbdebug.h b/src/tw/dbdebug.h new file mode 100644 index 0000000..048e163 --- /dev/null +++ b/src/tw/dbdebug.h @@ -0,0 +1,165 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//dbdebug.h + +#ifndef __DBDEBUG_H +#define __DBDEBUG_H + +#ifndef __FCODATASOURCEITER_H +#include "fco/fcodatasourceiter.h" +#endif +#ifndef __HIERDATABASE_H +#include "db/hierdatabase.h" +#endif +#ifndef __SREFCOUNTOBJ_H +#include "core/srefcountobj.h" +#endif +#ifndef __HIERDBNODE_H +#include "db/hierdbnode.h" +#endif + +// STL stuff... +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// FORWARD DECLARATIONS +//////////////////////////////////////////////////////////////////////////////// +class cBlockFile; +class cFCODatabaseFileIter; +struct cDbDebug_i; +class cDbDataSourceIter; +struct DbMapNode; +class cFCOName; + +///////////////////////////////////////////////////////////////////////////////// +// cDebugHierDb -- +// This derived class is a hack for accessing data that is usually protected. +// A static_cast is used to morph this class back into a (more candid) +// cHierDatabase.. +///////////////////////////////////////////////////////////////////////////////// + +class cDebugHierDb : public cHierDatabase +{ +public: + cDebugHierDb() : cHierDatabase() {} + + typedef std::vector BlockArray; + + // + // Methods for accessing the two data members of cBlockRecordFile that we + // are interested in. + cBlockFile* myGetBlockFile () { return GetBlockFile(); } + BlockArray* myGetBlockArray () { return GetBlockArray(); } +private: +}; + +////////////////////////////////////////////////////////////////////////////////// +// An iterator for the cDebugHierDb object. I need to get at some data +// in this object, too... +class cDebugHierDbIter : public cHierDatabaseIter +{ +public: + // + // Type Defines: + // + typedef std::vector< cHierEntry > EntryArray; + + // Ctor, Dtor: + ~cDebugHierDbIter () {} + cDebugHierDbIter ( cHierDatabase* pDb ) : cHierDatabaseIter( pDb ) {} + + // + // Methods for obtaining protected members of cHierDatabaseIter: + // + cHierAddr myGetCurrentAddr() { return GetCurrentAddr(); } + // We need this method to match the hierarchy information with that of the + // quantum database. + + // + // Methods for accessing data members: + // TODO: Get rid of the stuff I don't end up using. + // + EntryArray::iterator& myGetEntryArrayIt() { return mIter; } + EntryArray& myGetEntryArray() { return mEntries; } + cHierArrayInfo& myGetArrayInfo() { return mInfo; } + cHierAddr& myGetInfoAddr() { return mInfoAddr; } + cHierDbPath& myGetCurrPath() { return mCurPath; } + +}; + +///////////////////////////////////////////////////////////////////////////////// +// cDbDebug -- +// A tripwire mode for probing the hierarchical database +///////////////////////////////////////////////////////////////////////////////// +//TODO: Would I ever want to create this class on the stack? +class cDbDebug +{ +public: + //Ctor, Dtor + cDbDebug(); + ~cDbDebug(); + + static void Execute ( cFCODatabaseFileIter& dbIter, const TSTRING& dbFile ); + void MapQuantumDatabase ( cDebugHierDb& db ); + // Traverses a blockfile and records all valid addresses + void TraverseHierarchy ( cDebugHierDbIter pIter ); + // Traverses a hierarchical database and "updates" the map for addresses that it finds. + void MapHierDbNodes ( std::map< std::pair, int >& dbMap, std::pair, cDebugHierDbIter& ); + // Changes the map for a given address, in order to record entries that were found in the hierarchy. + void CongruencyTest ( void ); + // Looks at the map to see if all entries have been accounted for. + void OutputResults ( void ); + // Gives a clean report only if the two database representations match exactly. + + // + // The map that will be used to test for congruency between the quantum database + // and the hierarchical database. + // + typedef std::map< std::pair< int, int > , int > hierDbMap; + + hierDbMap* GetHierDbMap ( void ); + void DisplayDbMap ( void ); + // Displays the whole map TODO: Somehow the spacing in the output got messed up... + //void ManipDb ( cFCODatabaseFileIter& dbIter ); + // A hook to DbExplore-like code. For convenience only. + +private: + // (somewhat) Insulated implementation: + cDbDebug_i* mpData; +}; + + +#endif //__DBDEBUG_H + diff --git a/src/tw/dbexplore.cpp b/src/tw/dbexplore.cpp new file mode 100644 index 0000000..7c7c1a1 --- /dev/null +++ b/src/tw/dbexplore.cpp @@ -0,0 +1,477 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// dbexplore.cpp +// + +#include "stdtw.h" +#include "dbexplore.h" +#include "fcodatabasefile.h" +#include "dbdatasource.h" +#include "core/debug.h" +#include "core/error.h" +#include "fco/fcopropdisplayer.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" + +// +// TODO -- make an "associate with new genre" method for the db iter so we don't have to +// delete and create a new one when we switch genres. +// + +static inline bool IsSpace( TCHAR c ) +{ + return ( (c == _T(' ')) || (c == _T('\t')) || (c == _T('\r')) || (c == _T('\n')) || (c == _T('\0')) ); +} + +static inline bool IsEnd( TCHAR c ) +{ + return ( (c == _T('\0')) ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetNoun +// note -- you can only call this once after the verb (it eats the rest +// of the line!) +/////////////////////////////////////////////////////////////////////////////// +static void GetNoun( TSTRING& noun ) +{ + static TSTRING prevNoun; + TCHAR buf[1024]; + + TCIN.getline( buf, 1024 ); + // + // find the end of the noun... + // + TCHAR* pStart = buf; + TCHAR* end = &buf[1023]; + while( IsSpace(*pStart) && (! IsEnd(*pStart)) && (pStart < end) ) + pStart++; + + if( IsEnd( *pStart ) || (pStart >= end) ) + { + // no noun! + noun = _T(""); + return; + } + TCHAR* pCur = pStart; + bool bQuote = false; + if( *pCur == _T('\"') ) + { + bQuote = true; + pCur++; + pStart++; + } + while( pCur < end ) + { + if( (! bQuote) && IsSpace(*pCur) ) + break; + + if( *pCur == _T('\"') && bQuote) + break; + + pCur++; + } + noun.assign(pStart, (pCur - pStart)); + + if( noun.compare( _T("!$") ) == 0 ) + { + noun = prevNoun; + } + prevNoun = noun; +} + +/////////////////////////////////////////////////////////////////////////////// +// SeekTo -- seeks to the named noun; this takes care of interpriting special +// nouns. If the seek fails, then Done() is true and false is returned. +// If noun is a special character, then it is altered to what it mapped to. +/////////////////////////////////////////////////////////////////////////////// +static bool SeekTo(cDbDataSourceIter* pIter, TSTRING& noun ) +{ + if( noun[0] == _T('*') ) + { + // interprite the rest of the string as a number index to seek to... + int index = _ttoi( &noun[1] ); + if( index < 0 ) + return false; + pIter->SeekBegin(); + for( int i=0; ((i < index) && (! pIter->Done())); i++, pIter->Next() ) + { + + } + if( pIter->Done() ) + return false; + noun = pIter->GetShortName(); + return true; + } + else + return ( pIter->SeekTo( noun.c_str() ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +// PrintFCO +/////////////////////////////////////////////////////////////////////////////// +static void PrintFCO( const iFCO* pFCO, const iFCOPropDisplayer* pDisplayer ) +{ + TCOUT.setf(std::ios::left); + + TCOUT << _T("------- ") + << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pFCO->GetName() ) + << _T(" -------") + << std::endl; + // + // iterate over all of the properties + // + const iFCOPropSet* pPropSet = pFCO->GetPropSet(); + cFCOPropVector v = pPropSet->GetValidVector(); + for( int i=0; i < pPropSet->GetNumProps(); i++ ) + { + if( v.ContainsItem( i ) ) + { + TCOUT << _T("["); + TCOUT.width(2); + TCOUT << i << _T("]") ; + TCOUT.width(25); + TCOUT << pPropSet->GetPropName(i); + TCOUT.width(0); + TCOUT << pDisplayer->PropAsString( pFCO, i ) << std::endl; + } + } + TCOUT << _T("--------------------------------------------") << std::endl; +} + +static void SplitString( const TSTRING& str, TCHAR c, std::vector& vStrings ) +{ + vStrings.clear(); + + TSTRING::const_iterator i, prev; + for( prev = i = str.begin(); i != str.end(); i++ ) + { + if( *i == c ) + { + vStrings.push_back(TSTRING()); + vStrings.back().assign( prev, i ); + prev = i+1; + } + } + if( prev != i ) + { + vStrings.push_back(TSTRING()); + vStrings.back().assign( prev, i ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +void cDbExplore::Execute( cFCODatabaseFileIter& dbIter ) +{ + ASSERT( ! dbIter.Done() ); + + cDbDataSourceIter* pIter = new cDbDataSourceIter( &dbIter.GetDb(), dbIter.GetGenre() ); + const iFCOPropDisplayer* pDisplayer = dbIter.GetGenreHeader().GetPropDisplayer(); + + //////////////////////////// + // the main event loop... + //////////////////////////// + while( true ) + { + TSTRING verb, noun; + TCOUT << _T(">>"); + TCIN >> verb; + // + // ok, now we switch on the command... + // + //----------------------------------------------------------------- + // quit + //----------------------------------------------------------------- + if( verb.compare( _T("quit") ) == 0 ) + { + // the quit command... + break; + } + //----------------------------------------------------------------- + // print + //----------------------------------------------------------------- + if( verb.compare( _T("print") ) == 0 ) + { + GetNoun(noun); + if( SeekTo( pIter, noun ) ) + { + if( pIter->HasFCOData() ) + { + iFCO* pFCO = pIter->CreateFCO(); + PrintFCO( pFCO, pDisplayer ); + pFCO->Release(); + } + else + { + TCOUT << _T("Object has no data associated with it.") << std::endl; + } + } + else + { + TCOUT << _T("Unable to find object ") << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwd + //----------------------------------------------------------------- + else if( verb.compare( _T("pwd") ) == 0 ) + { + TCOUT << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pIter->GetParentName() ) << std::endl; + } + //----------------------------------------------------------------- + // ls + //----------------------------------------------------------------- + else if( verb.compare( _T("ls") ) == 0 ) + { + int cnt = 0; + for( pIter->SeekBegin(); ! pIter->Done(); pIter->Next(), cnt++ ) + { + TCOUT << _T("[") << cnt ; + if( pIter->CanDescend() ) + { + TCOUT << _T("]*\t") ; + } + else + { + TCOUT << _T("]\t") ; + } + TCOUT << pIter->GetShortName() << std::endl; + } + } + //----------------------------------------------------------------- + // cd + //----------------------------------------------------------------- + else if( verb.compare( _T("cd") ) == 0 ) + { + GetNoun(noun); + std::vector vDirs; + SplitString( noun, pIter->GetParentName().GetDelimiter(), vDirs ); + for( std::vector::iterator i = vDirs.begin(); i != vDirs.end(); i++ ) + { + + if( i->compare( _T("..") ) == 0 ) + { + if( pIter->AtRoot() ) + { + TCOUT << _T("Can't ascend above root.") << std::endl; + break; + } + else + { + TCOUT << _T("Ascending...") << std::endl; + pIter->Ascend(); + } + } + else + { + if( SeekTo( pIter, *i ) ) + { + if( pIter->CanDescend() ) + { + TCOUT << _T("Descending into ") << *i << std::endl; + pIter->Descend(); + } + else + { + TCOUT << *i << _T(" has no children; can't descend.") << std::endl; + break; + } + } + else + { + TCOUT << _T("Unable to find object ") << *i << std::endl; + break; + } + } + } + } + //----------------------------------------------------------------- + // cg + //----------------------------------------------------------------- + else if( verb.compare( _T("cg") ) == 0 ) + { + GetNoun(noun); + + cGenre::Genre newGenre = cGenreSwitcher::GetInstance()->StringToGenre( noun.c_str() ); + + if (newGenre != cGenre::GENRE_INVALID) + { + dbIter.SeekToGenre( newGenre ); + if( !dbIter.Done() ) + { + TCOUT << _T("Changing to Genre ") << noun << std::endl; + // + // create a new db iter for the new genre (db iters can only be + // assocaited with a single genre :-( ) + // + delete pIter; + pIter = new cDbDataSourceIter( &dbIter.GetDb(), newGenre ); + } + else + { + TCOUT << _T("Unable to find Genre ") << noun << std::endl; + } + } + else + { + TCOUT << _T("Invalid Genre ") << noun << std::endl; + } + } + //----------------------------------------------------------------- + // pwg + //----------------------------------------------------------------- + else if( verb.compare( _T("pwg") ) == 0 ) + { + TCOUT << _T("Current Genre: ") << cGenreSwitcher::GetInstance()->GenreToString( (cGenre::Genre)dbIter.GetGenre(), true ) << std::endl; + } + + //----------------------------------------------------------------- + // help + //----------------------------------------------------------------- + if( verb.compare( _T("help") ) == 0 ) + { + TCOUT << _T("Commands: ") << std::endl + << _T(" cd ") << std::endl + << _T(" pwd ") << std::endl + << _T(" ls ") << std::endl + << _T(" print ") << std::endl + << _T(" cg (FS | NTFS | NTREG)")<< std::endl + << _T(" pwg") << std::endl + << _T(" quit") << std::endl; + } + + // make sure the file is still valid... + // + /* +#ifdef _BLOCKFILE_DEBUG + db.AssertAllBlocksValid() ; +#endif + */ + } + + delete pIter; + TCOUT << _T("Exiting...") << std::endl; + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// old stuff +// +/////////////////////////////////////////////////////////////////////////////// +/* + + //----------------------------------------------------------------- + // mkdir + //----------------------------------------------------------------- + else if( verb.compare( _T("mkdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making a child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + iter.AddChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // mk + //----------------------------------------------------------------- + else if( verb.compare( _T("mk") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Making object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + TCOUT << "Error: object already exists!" << std::endl; + } + else + { + iter.AddFCO( noun, 0 ); // add a null fco for now + } + } + //----------------------------------------------------------------- + // rmdir + //----------------------------------------------------------------- + // TODO -- still needs to be implemented in the iterator class! + // + else if( verb.compare( _T("rmdir") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing the child of " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + //TODO -- check that it has an empty child + iter.DeleteChildArray(); + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + //----------------------------------------------------------------- + // rm + //----------------------------------------------------------------- + else if( verb.compare( _T("rm") ) == 0 ) + { + GetNoun(noun); + TCOUT << "Removing object " << noun << std::endl; + if( iter.SeekTo( noun.c_str() ) ) + { + if( iter.CanDescend() ) + { + TCOUT << "Can't delete object; it still has children." << std::endl; + } + else + { + iter.RemoveFCO(); + } + } + else + { + TCOUT << "Unable to find object " << noun << std::endl; + } + } + +*/ diff --git a/src/tw/dbexplore.h b/src/tw/dbexplore.h new file mode 100644 index 0000000..39f48f1 --- /dev/null +++ b/src/tw/dbexplore.h @@ -0,0 +1,48 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// dbexplore.h +// +#ifndef __DBEXPLORE_H +#define __DBEXPLORE_H + +class cFCODatabaseFileIter; + +class cDbExplore +{ +public: + static void Execute( cFCODatabaseFileIter& dbIter ); +}; + + +#endif //__DBEXPLORE_H + diff --git a/src/tw/fcodatabasefile.cpp b/src/tw/fcodatabasefile.cpp new file mode 100644 index 0000000..d048371 --- /dev/null +++ b/src/tw/fcodatabasefile.cpp @@ -0,0 +1,327 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatabasefile.cpp +// + +#include "stdtw.h" +#include "fcodatabasefile.h" +#include "core/archive.h" +#include "core/serializer.h" +#include "core/serializerutil.h" +#include "fco/fcogenre.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "core/fileheader.h" +#include "core/fsservices.h" +#include "db/blockrecordfile.h" + + +// TODO: May localizable strings need to be moved to string table + +IMPLEMENT_TYPEDSERIALIZABLE(cFCODatabaseFile, _T("cFCODatabaseFile"), 0, 1) + + +cFCODatabaseFile::tEntry::tEntry( cGenre::Genre genre ) +//TODO -- ugh, this sucks! I need to add another interface to the database! +: mDb ( cGenreSwitcher::GetInstance()->GetFactoryForGenre((cGenre::Genre)genre)->GetNameInfo()->IsCaseSensitive(), + cGenreSwitcher::GetInstance()->GetFactoryForGenre((cGenre::Genre)genre)->GetNameInfo()->GetDelimitingChar() + ), + mGenre( genre ) +{ +} + +cFCODatabaseFile::cFCODatabaseFile() +#ifdef _DEBUG +: mFileName( _T("Unknown file name") ) +#else +: mFileName( _T("") ) // If we don't know the filename, lets just not have one in release mode. +#endif +{ +} + +cFCODatabaseFile::~cFCODatabaseFile() +{ + for( DbList::iterator i = mDbList.begin(); i != mDbList.end(); i++ ) + { + delete *i; + } + mDbList.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Read +/////////////////////////////////////////////////////////////////////////////// +void cFCODatabaseFile::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Database Read"))); + + // + // read the db header.. + // + pSerializer->ReadObject( &mHeader ); + + int32 numGenre; + pSerializer->ReadInt32( numGenre ); + for( int i=0; i < numGenre; i++ ) + { + // read the genre number and throw if it is incorrect + // + int32 iGenre; + pSerializer->ReadInt32( iGenre ); + cGenre::Genre genre = (cGenre::Genre) iGenre; + + if( ! cGenreSwitcher::GetInstance()->IsGenreRegistered( genre ) ) + { + throw eSerializerInputStreamFmt(_T("Encountered unknown genre. Can not read database on this platform."), mFileName, eSerializer::TY_FILE); + } + + mDbList.push_back( new tEntry( genre ) ); + tEntry& entry = *(mDbList.back()); + // + // read the db genre header.. + // + pSerializer->ReadObject( &entry.mGenreHeader ); + // + // get the spec list + // + pSerializer->ReadObject( &entry.mSpecList ); + // + // get the database data + // + int32 fileSize; + pSerializer->ReadInt32( fileSize ); + // + // write the hier database into a temp file... + // + cLockedTemporaryFileArchive* pArch = new cLockedTemporaryFileArchive(); + pArch->OpenReadWrite(); + + cSerializerUtil::Copy( pArch, pSerializer, fileSize ); + // + // associate the database with this file... + // + entry.mDb.Open( pArch ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Write +/////////////////////////////////////////////////////////////////////////////// +void cFCODatabaseFile::Write(iSerializer* pSerializer) const //throw( eFCODbFileTooBig ) +{ + // + // write the db header.. + // + pSerializer->WriteObject( &mHeader ); + + // iterate through the genres, writing each one... + // + pSerializer->WriteInt32( mDbList.size() ); + // + // TODO -- the database is not really const-correct; therefore I have the sick casts below... + // + for( DbList::iterator i = const_cast(&mDbList)->begin(); i != const_cast(&mDbList)->end(); i++ ) + { + pSerializer->WriteInt32 ( (*i)->mGenre ); + pSerializer->WriteObject ( &(*i)->mGenreHeader ); + pSerializer->WriteObject ( &(*i)->mSpecList ); + // + // copy the database's data into the archive... + // + (*i)->mDb.Flush(); + cBidirArchive* pDbArch = (*i)->mDb.GetArchive(); + pDbArch->Seek( 0, cBidirArchive::BEGINNING ); + + // TODO:BAM -- eventually we should write it as a 64 bit, + // but that would change the db format + if( pDbArch->Length() > TSS_INT32_MAX ) + throw eFCODbFileTooBig(); + + pSerializer->WriteInt32( static_cast( pDbArch->Length() ) ); + cSerializerUtil::Copy( pSerializer, pDbArch, pDbArch->Length() ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFileHeaderID() +/////////////////////////////////////////////////////////////////////////////// +static cFileHeaderID gFCODatabaseFileHeaderID(_T("cFCODatabaseFile")); + +const cFileHeaderID& cFCODatabaseFile::GetFileHeaderID() +{ + return gFCODatabaseFileHeaderID; +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddGenre +/////////////////////////////////////////////////////////////////////////////// +void cFCODatabaseFile::AddGenre( cGenre::Genre genreId, cFCODatabaseFileIter* pIter ) +{ + // + // first, lets make sure this genre doesn't exist... + // + for( DbList::iterator i = mDbList.begin(); i != mDbList.end(); i++ ) + { + if( (*i)->mGenre == genreId ) + { + ASSERT( false ); + return; + } + } + // + // just add it to the front; I don't care about order + // + mDbList.push_back( new tEntry( genreId ) ); + if( pIter ) + { + pIter->mIter = mDbList.end()-1; + } + // + // create a new prop displayer for the header. + // + mDbList.back()->mGenreHeader.SetPropDisplayer + ( + cGenreSwitcher::GetInstance()->GetFactoryForGenre((cGenre::Genre)mDbList.back()->mGenre)->CreatePropDisplayer() + ); + // + // open the database + // + // + // the hier database will own destroying this... + // + cLockedTemporaryFileArchive* pArch = new cLockedTemporaryFileArchive(); + pArch->OpenReadWrite(); + mDbList.back()->mDb.Open( pArch ); + +} + + void cFCODatabaseFile::SetFileName( const TSTRING& name ) +{ + mFileName = name; +} + + TSTRING cFCODatabaseFile::GetFileName() const +{ + return mFileName; +} + +//----------------------------------------------------------------------------- +// cFCODatabaseFileIter +//----------------------------------------------------------------------------- +cFCODatabaseFileIter::cFCODatabaseFileIter( cFCODatabaseFile& dbFile ) +: mDbFile( dbFile ) +{ + SeekBegin(); +} + +void cFCODatabaseFileIter::SeekBegin() +{ + mIter = mDbFile.mDbList.begin(); +} + +void cFCODatabaseFileIter::Next() +{ + mIter++; +} + +bool cFCODatabaseFileIter::Done() const +{ + return ( mIter == mDbFile.mDbList.end() ); +} + +void cFCODatabaseFileIter::SeekToGenre(cGenre::Genre genreId) +{ + for( SeekBegin(); ! Done(); Next() ) + { + if( GetGenre() == genreId ) + return; + } +} + +void cFCODatabaseFileIter::Remove() +{ + ASSERT( ! Done() ); + if( ! Done() ) + { + delete *mIter; + mIter = mDbFile.mDbList.erase( mIter ); + } +} + +cGenre::Genre cFCODatabaseFileIter::GetGenre() const +{ + ASSERT( ! Done() ); + return (*mIter)->mGenre; +} + +cHierDatabase& cFCODatabaseFileIter::GetDb() +{ + ASSERT( ! Done() ); + return (*mIter)->mDb; +} + +const cHierDatabase& cFCODatabaseFileIter::GetDb() const +{ + ASSERT( ! Done() ); + return (*mIter)->mDb; + +} + +cFCOSpecList& cFCODatabaseFileIter::GetSpecList() +{ + ASSERT( ! Done() ); + return (*mIter)->mSpecList; +} + +const cFCOSpecList& cFCODatabaseFileIter::GetSpecList() const +{ + ASSERT( ! Done() ); + return (*mIter)->mSpecList; +} + +const cFCODbGenreHeader& cFCODatabaseFileIter::GetGenreHeader() const +{ + ASSERT( ! Done() ); + return (*mIter)->mGenreHeader; +} + +cFCODbGenreHeader& cFCODatabaseFileIter::GetGenreHeader() +{ + ASSERT( ! Done() ); + return (*mIter)->mGenreHeader; +} + + diff --git a/src/tw/fcodatabasefile.h b/src/tw/fcodatabasefile.h new file mode 100644 index 0000000..523dbad --- /dev/null +++ b/src/tw/fcodatabasefile.h @@ -0,0 +1,186 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcodatabasefile.h +// +#ifndef __FCODATABASEFILE_H +#define __FCODATABASEFILE_H + +class cHierDatabase; +class iFCOSpec; +class cFileHeaderID; +class cFCODatabaseFileIter; +class eArchive; +class eSerializer; +class cElGamalSigPublicKey; +class cElGamalSigPrivateKey; + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __HIERDATABASE_H +#include "db/hierdatabase.h" +#endif +#ifndef __FCOSPECLIST_H +#include "fco/fcospeclist.h" +#endif +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif +#ifndef __HEADERINFO_H +#include "tw/headerinfo.h" +#endif +#ifndef __ERROR_H +#include "core/error.h" +#endif +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +// +// TODO -- support encrypting each entry seperately +// +// TODO -- figure out some way to templatize this class based on encryption method +// + +TSS_EXCEPTION( eFCODbFile, eError ); +TSS_EXCEPTION( eFCODbFileTooBig, eFCODbFile ); + +//----------------------------------------------------------------------------- +// cFCODatabaseFile -- class that manages a set of databases (for different genres +// stored encrypted on disk +//----------------------------------------------------------------------------- +class cFCODatabaseFile : public iTypedSerializable +{ +public: + cFCODatabaseFile(); + virtual ~cFCODatabaseFile(); + + void SetFileName( const TSTRING& name ); + TSTRING GetFileName() const; + // the file name is only used in exception throwing; it is not necessary to set it. + + void AddGenre( cGenre::Genre genreId, cFCODatabaseFileIter* pIter = 0 ); //throw (eArchive) + // if pIter is not null, then it is pointing at the new node. This asserts that the + // genre doesn't currently exist + + cFCODbHeader& GetHeader(); + + static const cFileHeaderID& GetFileHeaderID(); + + /////////////////////////////// + // serialization interface + /////////////////////////////// + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + + typedef cFCODatabaseFileIter iterator; + //------------------------------------------------------------------------- + // cEntry -- a single entry in the database -- represents a genre's database + // note that if the entry hasn't been loaded from disk yet, all of its + // data members are NULL + //------------------------------------------------------------------------- + struct tEntry + { + tEntry( cGenre::Genre genre ); + // the ctor will get the appropriate database construction parameters + // based on the genre number. + ~tEntry( ) + { + + } + + cHierDatabase mDb; // the database; + cFCODbGenreHeader mGenreHeader; + cFCOSpecList mSpecList; // the spec used to create the database + cGenre::Genre mGenre; // the genre this is associated with + }; + +private: + cFCODatabaseFile( const cFCODatabaseFile& rhs ); //not impl + void operator= ( const cFCODatabaseFile& rhs ); //not impl + + typedef std::vector DbList; + friend class cFCODatabaseFileIter; + + cFCODbHeader mHeader; + DbList mDbList; // the list of databases + TSTRING mFileName; // for cosmetic purposes only + + DECLARE_TYPEDSERIALIZABLE() +}; + +//----------------------------------------------------------------------------- +// cFCODatabaseFileIter +//----------------------------------------------------------------------------- +class cFCODatabaseFileIter +{ +public: + cFCODatabaseFileIter( cFCODatabaseFile& dbFile ); + + void SeekBegin(); + void Next(); + bool Done() const; + int Size() const { return mDbFile.mDbList.size(); } + + void SeekToGenre(cGenre::Genre genreId); + // Done() is true if the genre doesn't exist + void Remove(); + // removes the current node from the database file + + cGenre::Genre GetGenre() const; + cHierDatabase& GetDb() ; + const cHierDatabase& GetDb() const; + cFCOSpecList& GetSpecList(); + const cFCOSpecList& GetSpecList() const; + cFCODbGenreHeader& GetGenreHeader(); + const cFCODbGenreHeader& GetGenreHeader() const; + +private: + cFCODatabaseFile& mDbFile ; + cFCODatabaseFile::DbList::iterator mIter; + + friend class cFCODatabaseFile; +}; + +//############################################################################# +// inline implementation +//############################################################################# + +inline cFCODbHeader& cFCODatabaseFile::GetHeader() +{ + return mHeader; +} + +#endif //__FCODATABASEFILE_H + diff --git a/src/tw/fcodatabasefile_t.cpp b/src/tw/fcodatabasefile_t.cpp new file mode 100644 index 0000000..e753410 --- /dev/null +++ b/src/tw/fcodatabasefile_t.cpp @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcodatabasefile.cpp +#include "stdtw.h" +#include "fcodatabasefile.h" + +void TestFCODatabaseFile() +{ + +} diff --git a/src/tw/fcodatabaseutil.cpp b/src/tw/fcodatabaseutil.cpp new file mode 100644 index 0000000..3ec5c0b --- /dev/null +++ b/src/tw/fcodatabaseutil.cpp @@ -0,0 +1,80 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////////////// +//fcodatabaseutil.cpp : Implements functions for maintaining +// fcodatabase objects. + +#include "stdtw.h" +#include "fcodatabaseutil.h" +#include + +//Headers necessary for traversing database objects: +#include "fco/fcopropdisplayer.h" +#include "fco/fco.h" +#include "core/debug.h" +#include "fco/iterproxy.h" +#include "fco/fconame.h" +#include "core/fsservices.h" +#include "headerinfo.h" +#include "core/timeconvert.h" +#include "fco/twfactory.h" +#include "twutil.h" + +/////////////////////////////////////////////////////////////////////////////////////// +// cFCODatabaseUtil +/////////////////////////////////////////////////////////////////////////////////////// + +void cFCODatabaseUtil::CalculateHeader( + cFCODbHeader& dbHeader, + const TSTRING& policyFilename, + const TSTRING& configFilename, + const TSTRING& dbFilename, + const TSTRING& commandLineParams, + int64 createTime, + int64 lastDBUpdateTime + ) +{ + cDebug d("cFCODatabaseUtil::CalculateHeaderInfo"); + + dbHeader.SetPolicyFilename (policyFilename); + dbHeader.SetConfigFilename (configFilename); + dbHeader.SetDBFilename (dbFilename); + dbHeader.SetSystemName (cTWUtil::GetSystemName()); + dbHeader.SetCommandLineParams (commandLineParams); + dbHeader.SetIPAddress (cTWUtil::GetIPAddress()); + dbHeader.SetCreator (cTWUtil::GetCurrentUser()); + dbHeader.SetHostID (cTWUtil::GetHostID()); + dbHeader.SetCreationTime (createTime); + dbHeader.SetLastDBUpdateTime (lastDBUpdateTime); +} + + diff --git a/src/tw/fcodatabaseutil.h b/src/tw/fcodatabaseutil.h new file mode 100644 index 0000000..bfc82e2 --- /dev/null +++ b/src/tw/fcodatabaseutil.h @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//fcodatabaseutil.h : Helper class for maintaining fcodatabase objects. + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __FCODATABASEUTIL_H +#define __FCODATABASEUTIL_H + +//Forward Class Declarations: +class cFCODbHeader; +class cFCODBHeaderInfo; + +//============================================================================= +// cFCODatabaseUtil -- A Utility class for cFCODatabase Objects. Contains static +// functions for calculating and storing system properties before saving a +// database object. +//============================================================================= +class cFCODatabaseUtil +{ +public: + static void CalculateHeader( + cFCODbHeader& dbHeader, + const TSTRING& policyFilename, + const TSTRING& configFilename, + const TSTRING& dbFilename, + const TSTRING& commandLineParams, + int64 createTime, + int64 lastDBUpdateTime + ); + //Calculates and gathers header data, stores results in header. +private: +}; + + +#endif //__FCODATABASEUTIL_H + diff --git a/src/tw/fcoreport.cpp b/src/tw/fcoreport.cpp new file mode 100644 index 0000000..0d1a1d4 --- /dev/null +++ b/src/tw/fcoreport.cpp @@ -0,0 +1,936 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoreport.h +/////////////////////////////////////////////////////////////////////////////// + +#include "stdtw.h" +#include "fcoreport.h" +#include "fcoreportutil.h" +#include "fco/fcospeclist.h" +#include "fco/fcosetimpl.h" +#include "fco/fcosetws.h" +#include "fco/fcospecutil.h" +#include "fco/fcopropvector.h" +#include "core/serializer.h" +#include "core/debug.h" +#include "core/errorbucketimpl.h" +#include "fco/iterproxy.h" +#include "core/hashtable.h" +#include "core/fsservices.h" +#include "fco/fcospecattr.h" +#include "core/fileheader.h" +#include "headerinfo.h" + +#include + +//============================================================================= +// class cFCOReport_i +//============================================================================= + +class cFCOReport_i +{ +public: + cFCOReport_i(); + ~cFCOReport_i(); + + // note that all iFCOs and all iFCOSpecs in this structure are AddRef()ed when added + // and will be Release()d when deleted. + struct cChangeNode + { + const iFCO* mpOldFCO; + const iFCO* mpNewFCO; + cFCOPropVector mChangeVector; + + cChangeNode(); + cChangeNode(const cChangeNode& rhs); + ~cChangeNode(); + void Clear(); + }; + + struct cNode + { + iFCOSpec* mpSpec; // _must_ be valid (non-0) + const cFCOSpecAttr* mpSpecAttr; // _must_ be valid (non-0) + cFCOSetWS mAdded; // these two sets make sure their fcos are in mpSpec. + cFCOSetWS mRemoved; + std::list mChanged; + cErrorQueue mErrorQueue; + int32 mnObjectsScanned; + + cNode(); + cNode(const cNode& rhs); + ~cNode(); + void Clear(); + }; + + + typedef std::list SpecList; + + struct cGenreNode + { + cGenreNode() {}; + cGenreNode( const cGenreNode& rhs ); + cFCOReportGenreHeader mGenreHeader; + cGenre::Genre mGenre; + SpecList mSpecList; + }; + + typedef std::list GenreSpecList; + + // data members + cErrorQueue mErrorQueue; // the general error queue + GenreSpecList mGenreList; +}; + + +cFCOReport_i::cGenreNode::cGenreNode( const cFCOReport_i::cGenreNode& rhs ) + : mGenreHeader( rhs.mGenreHeader ), mGenre( rhs.mGenre ), mSpecList( rhs.mSpecList ) +{ +} + +cFCOReport_i::cFCOReport_i() +{ +} + +cFCOReport_i::~cFCOReport_i() +{ +} + + +cFCOReport_i::cChangeNode::cChangeNode() +: mpOldFCO(0), + mpNewFCO(0) +{ +} + +cFCOReport_i::cChangeNode::cChangeNode(const cFCOReport_i::cChangeNode& rhs) +{ + mpOldFCO = rhs.mpOldFCO; + if (mpOldFCO) + mpOldFCO->AddRef(); + + mpNewFCO = rhs.mpNewFCO; + if (mpNewFCO) + mpNewFCO->AddRef(); + + mChangeVector = rhs.mChangeVector; +} + +cFCOReport_i::cChangeNode::~cChangeNode() +{ + Clear(); +} + +void cFCOReport_i::cChangeNode::Clear() +{ + if(mpOldFCO) + mpOldFCO->Release(); + if(mpNewFCO) + mpNewFCO->Release(); + mpOldFCO = mpNewFCO = 0; +} + +cFCOReport_i::cNode::cNode() : + mpSpec(0), + mpSpecAttr(0), + mAdded(0), + mRemoved(0), + mnObjectsScanned(0) +{ +} + +cFCOReport_i::cNode::cNode(const cFCOReport_i::cNode& rhs) +: mAdded(rhs.mAdded), + mRemoved(rhs.mRemoved) +{ + mpSpec = rhs.mpSpec; + if (mpSpec) + mpSpec->AddRef(); + + mpSpecAttr = rhs.mpSpecAttr; + if (mpSpecAttr) + mpSpecAttr->AddRef(); + + mChanged = rhs.mChanged; + mErrorQueue = rhs.mErrorQueue; + mnObjectsScanned = rhs.mnObjectsScanned; +} + +cFCOReport_i::cNode::~cNode() +{ + Clear(); +} + +void cFCOReport_i::cNode::Clear() +{ + mAdded.Clear(); + mAdded.SetSpec(0); + mRemoved.Clear(); + mRemoved.SetSpec(0); + mChanged.clear(); + mErrorQueue.Clear(); + if(mpSpec) + mpSpec->Release(); + if(mpSpecAttr) + mpSpecAttr->Release(); + mpSpec = 0; + mpSpecAttr = 0; + mnObjectsScanned = 0; +} + +//============================================================================= +// cFCOReportGenreIter +//============================================================================= + +class cFCOReportGenreIter_i +{ +public: + cFCOReport_i::GenreSpecList* mpList; + cFCOReport_i::GenreSpecList::iterator mIter; +}; + +cFCOReportGenreIter::cFCOReportGenreIter(const cFCOReport& report) +{ + mpData = new cFCOReportGenreIter_i; + + mpData->mpList = &report.mpData->mGenreList; + mpData->mIter = mpData->mpList->begin(); +} + +cFCOReportGenreIter::cFCOReportGenreIter(const cFCOReportGenreIter& rhs) +{ + mpData = new cFCOReportGenreIter_i; + + *this = rhs; +} + +cFCOReportGenreIter::~cFCOReportGenreIter() +{ + delete mpData; +} + +void cFCOReportGenreIter::operator=(const cFCOReportGenreIter& rhs) +{ + mpData->mpList = rhs.mpData->mpList; + mpData->mIter = rhs.mpData->mIter; +} + +// iteration methods +void cFCOReportGenreIter::SeekBegin() const +{ + mpData->mIter = mpData->mpList->begin(); +} + +void cFCOReportGenreIter::Next() const +{ + ++mpData->mIter; +} + +bool cFCOReportGenreIter::Done() const +{ + return mpData->mIter == mpData->mpList->end(); +} + +// seeks to specific genre. Returns false if genre does not exist in report +bool cFCOReportGenreIter::SeekToGenre(cGenre::Genre genre) +{ + for (mpData->mIter = mpData->mpList->begin(); ; ++mpData->mIter) + { + if (mpData->mIter == mpData->mpList->end()) + return false; + + if (mpData->mIter->mGenre == genre) + break; + } + + return true; +} + +// removes the entire genre from report +void cFCOReportGenreIter::Remove() +{ + ASSERT(!Done()); + + mpData->mIter = mpData->mpList->erase(mpData->mIter); +} + +cFCOReportGenreHeader& cFCOReportGenreIter::GetGenreHeader() const +{ + return mpData->mIter->mGenreHeader; +} + +// Get current genre +cGenre::Genre cFCOReportGenreIter::GetGenre() const +{ + if (mpData->mIter == mpData->mpList->end()) + { + ASSERT(false); + return cGenre::GENRE_INVALID; + } + + return mpData->mIter->mGenre; +} + +//============================================================================= +// cFCOReportSpecIter +//============================================================================= + +class cFCOReportSpecIter_i +{ +public: + cFCOReport_i::SpecList* mpList; + cFCOReport_i::SpecList::iterator mIter; +}; + +///////////////////////// +// ctor and dtor +///////////////////////// +cFCOReportSpecIter::cFCOReportSpecIter(const cFCOReport& report, cGenre::Genre genre) +{ + mpData = 0; + + cFCOReport_i::GenreSpecList::iterator genreIter; + for (genreIter = report.mpData->mGenreList.begin(); ; ++genreIter) + { + if (genreIter == report.mpData->mGenreList.end()) + { + ASSERT(false); + THROW_INTERNAL("fcoreport.cpp"); + } + + if (genreIter->mGenre == genre) + break; + } + + mpData = new cFCOReportSpecIter_i(); + mpData->mpList = &genreIter->mSpecList; + mpData->mIter = mpData->mpList->begin(); +} + +cFCOReportSpecIter::cFCOReportSpecIter(cFCOReport& report, cGenre::Genre genre) +{ + mpData = 0; + + cFCOReport_i::GenreSpecList::iterator genreIter; + for (genreIter = report.mpData->mGenreList.begin(); ; ++genreIter) + { + if (genreIter == report.mpData->mGenreList.end()) + { + // add an empty spec to the report + report.AddSpec(genre, 0, 0, 0); + genreIter = report.mpData->mGenreList.end(); + --genreIter; + ASSERT(genreIter->mGenre == genre); + } + + if (genreIter->mGenre == genre) + break; + } + + mpData = new cFCOReportSpecIter_i(); + mpData->mpList = &genreIter->mSpecList; + mpData->mIter = mpData->mpList->begin(); +} + +cFCOReportSpecIter::cFCOReportSpecIter(const cFCOReportGenreIter& genreIter) +{ + mpData = new cFCOReportSpecIter_i(); + mpData->mpList = &genreIter.mpData->mIter->mSpecList; + mpData->mIter = mpData->mpList->begin(); +} + +cFCOReportSpecIter::~cFCOReportSpecIter() +{ + delete mpData; +} + +cFCOReportSpecIter::cFCOReportSpecIter(const cFCOReportSpecIter& rhs) +{ + mpData = new cFCOReportSpecIter_i(); + *this = rhs; +} + +void cFCOReportSpecIter::operator=(const cFCOReportSpecIter& rhs) +{ + if (mpData == 0) + mpData = new cFCOReportSpecIter_i(); + + mpData->mpList = rhs.mpData->mpList; + mpData->mIter = rhs.mpData->mIter; +} + +int cFCOReportSpecIter::GetNumChanged() const +{ + ASSERT(! Done()); + return mpData ? mpData->mIter->mChanged.size() : 0; +} + +void cFCOReportSpecIter::SetObjectsScanned( int nObjectsScanned ) +{ + ASSERT(mpData != 0); + if (mpData == 0) + THROW_INTERNAL("fcoreport.cpp"); + + mpData->mIter->mnObjectsScanned = nObjectsScanned; +} + +int cFCOReportSpecIter::GetObjectsScanned() const +{ + ASSERT(! Done()); + return mpData ? mpData->mIter->mnObjectsScanned : 0; +} + +void cFCOReportSpecIter::Remove() +{ + ASSERT(! Done()); + mpData->mIter->Clear(); + mpData->mIter = mpData->mpList->erase(mpData->mIter); +} + +///////////////////////// +// iteration methods +///////////////////////// +void cFCOReportSpecIter::SeekBegin() const +{ + if (mpData) + mpData->mIter = mpData->mpList->begin(); +} + +void cFCOReportSpecIter::Next() const +{ + ASSERT(mpData != 0); + mpData->mIter++; +} + +bool cFCOReportSpecIter::Done() const +{ + return mpData ? (mpData->mIter == mpData->mpList->end()) : true; +} + +const iFCOSpec* cFCOReportSpecIter::GetSpec() const +{ + ASSERT(! Done()); + return mpData ? (mpData->mIter->mpSpec) : 0; +} + +bool cFCOReportSpecIter::SeekToSpec(const iFCOSpec* pSpec) +{ + if (mpData) + for(mpData->mIter = mpData->mpList->begin(); mpData->mIter != mpData->mpList->end(); mpData->mIter++) + { + if(iFCOSpecUtil::FCOSpecEqual(*mpData->mIter->mpSpec, *pSpec)) + return true; + } + + return false; +} + +const cFCOSpecAttr* cFCOReportSpecIter::GetAttr() const +{ + ASSERT(! Done()); + return mpData ? (mpData->mIter->mpSpecAttr) : 0; +} + +const cErrorQueue* cFCOReportSpecIter::GetErrorQueue() const +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mErrorQueue) : 0; +} + +cErrorQueue* cFCOReportSpecIter::GetErrorQueue() +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mErrorQueue) : 0; +} + +const iFCOSet* cFCOReportSpecIter::GetAddedSet() const +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mAdded) : 0; +} + +iFCOSet* cFCOReportSpecIter::GetAddedSet() +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mAdded) : 0; +} + +const iFCOSet* cFCOReportSpecIter::GetRemovedSet() const +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mRemoved) : 0; +} + +iFCOSet* cFCOReportSpecIter::GetRemovedSet() +{ + ASSERT(! Done()); + return mpData ? (&mpData->mIter->mRemoved) : 0; +} + +//============================================================================= +// class cFCOReportChangeIter +//============================================================================= +class cFCOReportChangeIter_i +{ +public: + std::list* mpList; + std::list::iterator mIter; +}; + +cFCOReportChangeIter::cFCOReportChangeIter(const cFCOReportSpecIter& specIter) +{ + ASSERT(!specIter.Done()); + mpData = new cFCOReportChangeIter_i; + SetSpecIter(specIter); +} + +cFCOReportChangeIter::cFCOReportChangeIter() +{ + mpData = new cFCOReportChangeIter_i; + mpData->mpList = 0; + mpData->mIter = mpData->mpList->begin(); +} + +cFCOReportChangeIter::cFCOReportChangeIter(const cFCOReportChangeIter& rhs) +{ + mpData = new cFCOReportChangeIter_i; + *this = rhs; +} + +cFCOReportChangeIter::~cFCOReportChangeIter() +{ + delete mpData; +} + +void cFCOReportChangeIter::operator=(const cFCOReportChangeIter& rhs) +{ + mpData->mpList = rhs.mpData->mpList; + mpData->mIter = rhs.mpData->mIter; +} + +void cFCOReportChangeIter::SetSpecIter(const cFCOReportSpecIter& specIter) +{ + ASSERT(! specIter.Done()); + mpData->mpList = &specIter.mpData->mIter->mChanged; + mpData->mIter = mpData->mpList->begin(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Remove +/////////////////////////////////////////////////////////////////////////////// +void cFCOReportChangeIter::Remove() +{ + ASSERT(! Done()); + mpData->mIter->Clear(); + mpData->mIter = mpData->mpList->erase(mpData->mIter); +} + +void cFCOReportChangeIter::SeekBegin() const +{ + ASSERT(mpData->mpList != 0); + mpData->mIter = mpData->mpList->begin(); +} + +void cFCOReportChangeIter::Next() const +{ + ASSERT(mpData->mpList != 0); + mpData->mIter++; +} + +bool cFCOReportChangeIter::Done() const +{ + ASSERT(mpData->mpList != 0); + if(! mpData->mpList) + return true; + return (mpData->mIter == mpData->mpList->end()); +} + +const iFCO* cFCOReportChangeIter::GetOld() const +{ + ASSERT(! Done()); + return (mpData->mIter->mpOldFCO); +} + + +const iFCO* cFCOReportChangeIter::GetNew() const +{ + ASSERT(! Done()); + return (mpData->mIter->mpNewFCO); +} + + +const cFCOPropVector& cFCOReportChangeIter::GetChangeVector() const +{ + ASSERT(! Done()); + return (mpData->mIter->mChangeVector); +} + +//============================================================================= +// class cFCOReport +//============================================================================= + +IMPLEMENT_TYPEDSERIALIZABLE(cFCOReport, _T("cFCOReport"), 0, 1); + +cFCOReport::cFCOReport() +{ + mpData = new cFCOReport_i; +} + +cFCOReport::~cFCOReport() +{ + ClearReport(); + delete mpData; +} + +//////////////////////////////////////////////////////////// + +cErrorQueue* cFCOReport::GetErrorQueue() +{ + return &mpData->mErrorQueue; +} + +const cErrorQueue* cFCOReport::GetErrorQueue() const +{ + return &mpData->mErrorQueue; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetNumSpecs +/////////////////////////////////////////////////////////////////////////////// +int cFCOReport::GetNumSpecs(cGenre::Genre genre) const +{ + cFCOReport_i::GenreSpecList::iterator genreIter; + for (genreIter = mpData->mGenreList.begin(); ; ++genreIter) + { + if (genreIter == mpData->mGenreList.end()) + { + return 0; + } + + if (genreIter->mGenre == genre) + break; + } + + return genreIter->mSpecList.size(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ClearReport +/////////////////////////////////////////////////////////////////////////////// +void cFCOReport::ClearReport() +{ + mpData->mGenreList.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// AddSpec +/////////////////////////////////////////////////////////////////////////////// +void cFCOReport::AddSpec(cGenre::Genre genre, const iFCOSpec* pSpec, const cFCOSpecAttr* pAttr, cFCOReportSpecIter* pIter) +{ + // look up the genre + cFCOReport_i::GenreSpecList::iterator genreIter; + for (genreIter = mpData->mGenreList.begin(); ; ++genreIter) + { + if (genreIter == mpData->mGenreList.end()) + { + cFCOReport_i::cGenreNode newGenre; + newGenre.mGenre = genre; + + mpData->mGenreList.push_back(newGenre); + + genreIter = mpData->mGenreList.end(); + --genreIter; + break; + } + + if (genreIter->mGenre == genre) + break; + } + + if (pSpec == 0) + { + ASSERT(pAttr == 0); + ASSERT(pIter == 0); + return; + } + + // make sure this spec doesn't overlap any others + cFCOReport_i::SpecList::iterator specIter; + for(specIter = genreIter->mSpecList.begin(); specIter != genreIter->mSpecList.end(); ++specIter) + { + // TODO -- what is the right action to take? + if(iFCOSpecUtil::SpecsOverlap(pSpec, specIter->mpSpec)) + { + ASSERT(false); + THROW_INTERNAL("fcoreport.cpp"); + } + } + + genreIter->mSpecList.push_back(cFCOReport_i::cNode()); + cFCOReport_i::cNode& node = genreIter->mSpecList.back(); + node.mpSpec = pSpec->Clone(); + node.mpSpecAttr = pAttr; + pAttr->AddRef(); + node.mAdded.SetSpec(node.mpSpec); + node.mRemoved.SetSpec(node.mpSpec); + + // fill out the iterator + if (pIter && pIter->mpData && pIter->mpData->mpList == &genreIter->mSpecList) + { + pIter->mpData->mIter = genreIter->mSpecList.end(); + pIter->mpData->mIter--; + ASSERT(pIter->GetSpec() == node.mpSpec); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddChangedFCO +/////////////////////////////////////////////////////////////////////////////// +void cFCOReport::AddChangedFCO(const cFCOReportSpecIter& iter, const iFCO* pOldFCO, const iFCO* pNewFCO, const cFCOPropVector& changedProps) +{ + cDebug d("cFCOReport::AddChangedFCO"); + + // make some assertions about the iterator + + #ifdef _DEBUG + // make sure iter points to one of our spec lists + cFCOReport_i::GenreSpecList::iterator genreIter; + for (genreIter = mpData->mGenreList.begin(); ; ++genreIter) + { + if (genreIter == mpData->mGenreList.end()) + { + ASSERT(false); + THROW_INTERNAL("fcoreport.cpp"); + } + + if (&genreIter->mSpecList == iter.mpData->mpList) + break; + } + #endif + + ASSERT(! iter.Done()); // make sure it points to something valid + + // some sanity checking for the fco names... + ASSERT(pOldFCO->GetName().IsEqual(pNewFCO->GetName())); + ASSERT((iter.GetSpec()->SpecContainsFCO(pOldFCO->GetName()))); + + iter.mpData->mIter->mChanged.push_back(cFCOReport_i::cChangeNode()); + cFCOReport_i::cChangeNode& changeNode = iter.mpData->mIter->mChanged.back(); + changeNode.mpOldFCO = pOldFCO; + changeNode.mpNewFCO = pNewFCO; + changeNode.mChangeVector = changedProps; + pOldFCO->AddRef(); + pNewFCO->AddRef(); +} + +/////////////////////////////////////////////////////////////////////////////// +// iSerializable interface +/////////////////////////////////////////////////////////////////////////////// +void cFCOReport::Read(iSerializer* pSerializer, int32 version) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("Report Read"))); + + ClearReport(); + + // read in main error queue + pSerializer->ReadObject(&mpData->mErrorQueue); + + // read in the genres + int32 genreIter, genreCount; + int32 specIter, specCount; + + pSerializer->ReadInt32(genreCount); + for (genreIter = 0; genreIter < genreCount; genreIter++) + { + cFCOReport_i::cGenreNode newGenre; + int32 genre; + + // TODO:BAM -- this used to be int16, so take care of backwards compatability + pSerializer->ReadInt32(genre); + newGenre.mGenre = (cGenre::Genre)genre; + + pSerializer->ReadObject( &newGenre.mGenreHeader ); + + pSerializer->ReadInt32(specCount); + for (specIter = 0; specIter < specCount; specIter++) + { + newGenre.mSpecList.push_back(cFCOReport_i::cNode()); + cFCOReport_i::cNode& node = newGenre.mSpecList.back(); + + node.mpSpec = static_cast (pSerializer->ReadObjectDynCreate()); + node.mpSpecAttr = static_cast(pSerializer->ReadObjectDynCreate()); + + pSerializer->ReadObject(&node.mErrorQueue); + pSerializer->ReadObject(&node.mAdded); + pSerializer->ReadObject(&node.mRemoved); + pSerializer->ReadInt32( node.mnObjectsScanned ); + + node.mAdded.SetSpec(node.mpSpec); + node.mRemoved.SetSpec(node.mpSpec); + + int32 changeSize; + pSerializer->ReadInt32(changeSize); + for(int j=0; j(pSerializer->ReadObjectDynCreate()); + cnode.mpNewFCO = static_cast(pSerializer->ReadObjectDynCreate()); + cnode.mChangeVector.Read(pSerializer); + } + } + + mpData->mGenreList.push_back(newGenre); + } + + // TODO -- we should do some kind of test here to ensure that all the data we read + // is consistant (ie -- no overlapping specs) +} + +void cFCOReport::Write(iSerializer* pSerializer) const +{ + cFCOReport_i::GenreSpecList::iterator genreIter; + cFCOReport_i::SpecList::iterator specIter; + + // write out the main error queue + pSerializer->WriteObject(&mpData->mErrorQueue); + + // iteratate over genres + pSerializer->WriteInt32(mpData->mGenreList.size()); + + for (genreIter = mpData->mGenreList.begin(); genreIter != mpData->mGenreList.end(); ++genreIter) + { + // TODO:BAM -- this used to be int16, so take care of backwards compatability + pSerializer->WriteInt32(genreIter->mGenre); + pSerializer->WriteObject( &genreIter->mGenreHeader ); + + + // write each node out... + pSerializer->WriteInt32(genreIter->mSpecList.size()); + + for (specIter = genreIter->mSpecList.begin(); specIter != genreIter->mSpecList.end(); ++specIter) + { + pSerializer->WriteObjectDynCreate(specIter->mpSpec); + pSerializer->WriteObjectDynCreate(specIter->mpSpecAttr); + pSerializer->WriteObject(&specIter->mErrorQueue); + pSerializer->WriteObject(&specIter->mAdded); + pSerializer->WriteObject(&specIter->mRemoved); + pSerializer->WriteInt32( specIter->mnObjectsScanned ); + + std::list::iterator changedIter; + pSerializer->WriteInt32(specIter->mChanged.size()); + for(changedIter = specIter->mChanged.begin(); changedIter != specIter->mChanged.end(); ++changedIter) + { + pSerializer->WriteObjectDynCreate(changedIter->mpOldFCO); + pSerializer->WriteObjectDynCreate(changedIter->mpNewFCO); + changedIter->mChangeVector.Write(pSerializer); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFileHeaderID() +/////////////////////////////////////////////////////////////////////////////// + +struct cFCOReportFHID { + cFileHeaderID* ReportID; + + cFCOReportFHID() { ReportID = 0; } + ~cFCOReportFHID() { delete ReportID; } +} gFCOReportFHID; + +const cFileHeaderID& cFCOReport::GetFileHeaderID() +{ + if (gFCOReportFHID.ReportID == 0) + gFCOReportFHID.ReportID = new cFileHeaderID(CLASS_TYPE(cFCOReport).AsString()); + + // sanity check + ASSERT(*gFCOReportFHID.ReportID == cFileHeaderID(CLASS_TYPE(cFCOReport).AsString())); + + return *gFCOReportFHID.ReportID; +} + + +void cFCOReport::TraceContents(int dl) const +{ + if(dl < 0) + dl = cDebug::D_DEBUG; + + cDebug d("cFCOReport:"); + + d.TraceDebug("Global Error Queue:\n"); + mpData->mErrorQueue.TraceContents(dl); + + cFCOReport_i::GenreSpecList::iterator genreIter; + cFCOReport_i::SpecList::iterator specIter; + + for (genreIter = mpData->mGenreList.begin(); genreIter != mpData->mGenreList.end(); ++genreIter) + { + d.Trace(dl, "> Genre [%d]:\n", (int)genreIter->mGenre); + + int specCount = 0; + for (specIter = genreIter->mSpecList.begin(); specIter != genreIter->mSpecList.end(); ++specIter, ++specCount) + { + d.Trace(dl, ">>> Spec [%d]:\n", specCount); + ASSERT(specIter->mpSpec != 0); + specIter->mpSpec->TraceContents(dl); + specIter->mpSpecAttr->TraceContents(dl); + specIter->mErrorQueue.TraceContents(dl); + + // trace out added & removed files + d.TraceDebug(">>> Added Files:\n"); + specIter->mAdded.TraceContents(dl); + d.TraceDebug(">>> Removed Files:\n"); + specIter->mRemoved.TraceContents(dl); + + // trace out changed files + d.TraceDebug(">>> Changed Files:\n"); + std::list::iterator changedIter; + int changeCounter = 0; + for (changedIter = specIter->mChanged.begin(); changedIter != specIter->mChanged.end(); ++changedIter, ++changeCounter) + { + d.Trace(dl, ">>>>> Changed fco [%d]\n", changeCounter); + d.Trace(dl, ">>>>> Old FCO:\n"); + (*changedIter).mpOldFCO->TraceContents(dl); + d.Trace(dl, ">>>>> New FCO:\n"); + (*changedIter).mpNewFCO->TraceContents(dl); + (*changedIter).mChangeVector.TraceContents(dl); + } + } + } +} + + diff --git a/src/tw/fcoreport.h b/src/tw/fcoreport.h new file mode 100644 index 0000000..6b26cb4 --- /dev/null +++ b/src/tw/fcoreport.h @@ -0,0 +1,259 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoreport.h +// +// class cFCOReport -- the tripwire report class + +#ifndef __FCOREPORT_H +#define __FCOREPORT_H + +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cFCOReport -- The information from an integrity check. +// +// This class must encompass all the information from an integrity check: +// +// * It must report each added, removed or changed FCO. +// +// * It must contain enough information to determine what line the in the policy +// file caused each FCO change to be reported. +// +// * It must contain enough information to update the database when the user +// OK's a FCO change. +// +// To store all of this information we organize by the specifier list that +// was used to create the report. During integrity checking each cFCOSpec +// will generate an cFCOSet of added FCO's, an cFCOSet of removed FCO's, +// and a pair of cFCOSet's for each changed FCO (a cFCOSet for the old +// properties of the FCO's and a cFCOSet for new properties of the FCO). +// There will also be a cPropertyVector to specify what properties differ +// between the old and new FCO for the changed set. +// +// The information in the report will be organized by cFCOSpec. For each +// cFCOSpec there will be a corresponding added FCO set, removed FCO set, +// and for changed fcos a new and old cFCOset and a changed mask. +/////////////////////////////////////////////////////////////////////////////// + +class cFCOName; +class cFCOReport_i; +class cFCOReportGenreIter_i; +class cFCOReportSpecIter_i; +class cFCOReportChangeIter_i; +class iFCOSpec; +class iFCOSet; +class iFCO; +class cFCOPropVector; +class cFCOSpecAttr; +class cFCOReportUtil; +class cFileHeaderID; +class cErrorQueue; +class cFCOReportGenreHeader; +class cFCOReportSpecIter; + +class cFCOReport : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + friend class cFCOReportSpecIter; + friend class cFCOReportUtil; + friend class cFCOReportGenreIter; +public: + cFCOReport(); + virtual ~cFCOReport(); + + void ClearReport(); + + void AddSpec(cGenre::Genre genre, const iFCOSpec* pSpec, const cFCOSpecAttr* pAttr, cFCOReportSpecIter* pIter = NULL); + // Add a spec to the report. The report will save copies of all three of these + // objects in its internal data structure. + // If pSpec, pAttr, and pIter are all NULL, an empty genre is added to report + // if pIter is passed in, it will be updated to point at the newly added spec. + // if genre is not in this report, it will be added + // if this spec overlaps another spec, an eInternal will be thrown + + void AddChangedFCO(const cFCOReportSpecIter& iter, const iFCO* pOldFCO, const iFCO* pNewFCO, const cFCOPropVector& changedProps); + // For the spec pointed to by the iter, add a changed FCO pair and property vector. + + const cErrorQueue* GetErrorQueue() const; + cErrorQueue* GetErrorQueue(); + // returns a pointer to the report's error queue. The caller is free to iterate over the errors, remove all the + // errors, or chain an error bucket to or from the report's error queue. + + int GetNumSpecs(cGenre::Genre genre) const; + // returns the number of specs in the report; these can be iterated over using the iterators below. + // returns 0 if genre is not in report + + void TraceContents(int dl = -1) const; + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + + static const cFileHeaderID& GetFileHeaderID(); + // Return a cFileHeaderID for all databases + +protected: + cFCOReport_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// iterator classes -- iterates over all the specs in the report and returns +// refrences to all the spec's related data +/////////////////////////////////////////////////////////////////////////////// +class cFCOReportGenreIter +{ + friend class cFCOReport; + friend class cFCOReportSpecIter; + friend class cFCOReportChangeIter; +public: + explicit cFCOReportGenreIter(const cFCOReport& report); + cFCOReportGenreIter(const cFCOReportGenreIter& rhs); + ~cFCOReportGenreIter(); + + void operator=(const cFCOReportGenreIter& rhs); + + // iteration methods + void SeekBegin() const; + void Next() const; + bool Done() const; + + bool SeekToGenre(cGenre::Genre genre); + // seeks to specific genre. Returns false if genre does not exist in report + + void Remove(); + // removes the entire genre from report + + // access to data + cGenre::Genre GetGenre() const; + // Get current genre + cFCOReportGenreHeader& GetGenreHeader() const; + +private: + cFCOReportGenreIter_i* mpData; +}; + +class cFCOReportSpecIter +{ + friend class cFCOReport; + friend class cFCOReportChangeIter; +public: + cFCOReportSpecIter(const cFCOReport& report, cGenre::Genre genre); + // if genre does not exist in the report, an eInternal error will be thrown. + cFCOReportSpecIter(cFCOReport& report, cGenre::Genre genre); + // if genre does not exist in the report, it will be added to the report with + // and empty spec list. + cFCOReportSpecIter(const cFCOReportGenreIter& genreIter); + // thorws eInternal if genreIter is not at a valid genre or is Done() + + cFCOReportSpecIter(const cFCOReportSpecIter& rhs); + ~cFCOReportSpecIter(); + + void operator=(const cFCOReportSpecIter& rhs); + + // iteration methods + void SeekBegin() const; + void Next() const; + bool Done() const; + + bool SeekToSpec(const iFCOSpec* pSpec); + // seeks to the first spec that equals the passed in one; returns false + // and seeks to end if not found. + + void Remove(); + // removes the spec and all fcos associated wit hit. Behavior is undefined if (Done() == true). + // after the erase, the iterator points to the next element in the list + + // access to data + const iFCOSpec* GetSpec() const; + const cFCOSpecAttr* GetAttr() const; + const cErrorQueue* GetErrorQueue() const; + cErrorQueue* GetErrorQueue(); + const iFCOSet* GetAddedSet() const; + iFCOSet* GetAddedSet(); + const iFCOSet* GetRemovedSet() const; + iFCOSet* GetRemovedSet(); + + int GetNumChanged() const; + // returns the number of fcos in the changed list. + // you access the members of the list by using the iterator below... + + void SetObjectsScanned( int nObjectsScanned ); + int GetObjectsScanned() const; + +private: + cFCOReportSpecIter_i* mpData; + // TODO -- if it turns out that we are creating a lot of these, we should consider + // making a pool of them. +}; + +class cFCOReportChangeIter +{ +public: + cFCOReportChangeIter(const cFCOReportSpecIter& specIter); + cFCOReportChangeIter(); + cFCOReportChangeIter(const cFCOReportChangeIter& rhs); + ~cFCOReportChangeIter(); + + void operator=(const cFCOReportChangeIter& rhs); + void SetSpecIter(const cFCOReportSpecIter& specIter); + // assocaite this iterator with a different spec. We will assert + // that specIter.Done() is not true. + + void Remove(); + // removes the the change entry pointed at by this iter. Behavior is undefined if (Done() == true). + // after the erase, the iterator points to the next element in the list + + // iteration methods + void SeekBegin() const; + void Next() const; + bool Done() const; + + // access to data... + const iFCO* GetOld() const; + const iFCO* GetNew() const; + const cFCOPropVector& GetChangeVector() const; + +private: + cFCOReportChangeIter_i* mpData; + // TODO -- if it turns out that we are creating a lot of these, we should consider + // making a pool of them. +}; + +#endif //__FCOREPORT_H + diff --git a/src/tw/fcoreport_t.cpp b/src/tw/fcoreport_t.cpp new file mode 100644 index 0000000..a56cf8d --- /dev/null +++ b/src/tw/fcoreport_t.cpp @@ -0,0 +1,172 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcoreport_t.cpp + +#include "stdtw.h" +#include "fcoreport.h" +#include "fco/fcospecimpl.h" +#include "fco/fcosetimpl.h" +#include "fs/fsobject.h" +#include "core/serializerimpl.h" +#include "core/archive.h" +#include "test/test.h" +#include "core/errorbucketimpl.h" +#include "fco/fcospecattr.h" +#include "fco/fcospechelper.h" +#include + +// we use this instead of TraceContents() so we can test the report iterators. +static void TraceReport(const cFCOReport& r, cDebug& d) +{ + d.TraceDebug("Global Error Queue:\n"); + r.GetErrorQueue()->TraceContents(); + + cFCOReportGenreIter genreIter(r); + int genreCount = 0; + + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next(), ++genreCount) + { + d.TraceDebug("> Genre [%d]:\n", genreCount); + + cFCOReportSpecIter specIter(genreIter); + int specCount = 0; + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next(), ++specCount) + { + d.TraceDebug(">>> Spec [%d]:\n", specCount); + ASSERT(specIter.GetSpec()); + specIter.GetSpec()->TraceContents(); + specIter.GetAttr()->TraceContents(); + specIter.GetErrorQueue()->TraceContents(); + + d.TraceDebug(">>> Added Files:\n"); + specIter.GetAddedSet()->TraceContents(); + d.TraceDebug(">>> Removed Files:\n"); + specIter.GetRemovedSet()->TraceContents(); + + // trace out changed files + cFCOReportChangeIter changeIter(specIter); + int changeCtr = 0; + for(changeIter.SeekBegin(); ! changeIter.Done(); changeIter.Next(), changeCtr++) + { + d.TraceDebug(">>>>> Changed fco [%d]\n", changeCtr); + d.TraceDebug(">>>>> Old FCO:\n"); + changeIter.GetOld()->TraceContents(); + d.TraceDebug(">>>>> New FCO:\n"); + changeIter.GetNew()->TraceContents(); + changeIter.GetChangeVector().TraceContents(); + } + } + } +} + +void TestFCOReport() +{ + cDebug d("TestFCOReport"); + + + cFCOSpecImpl* pSpec = new cFCOSpecImpl(_T("/etc"), NULL, new cFCOSpecStopPointSet); + cFCOSpecAttr* pAttr = new cFCOSpecAttr; + cFSObject* addedFCO = new cFSObject(cFCOName(_T("/etc/added_file"))); + cFSObject* removedFCO = new cFSObject(cFCOName(_T("/etc/removed_file"))); + cFSObject* changedFCO = new cFSObject(cFCOName(_T("/etc/changed_file"))); + cFSObject* oldChangedFCO = new cFSObject(cFCOName(_T("/etc/changed_file"))); + cFSObject* newChangedFCO = new cFSObject(cFCOName(_T("/etc/changed_file"))); + cFCOPropVector changedPropVector; + + //Calculate the time taken to generate the test report: + time_t* dummy_arg = NULL; + time_t time_finish; + //time_t time_begin = time(dummy_arg); + + { + cFCOReport report; + + changedPropVector.AddItem(cFSPropSet::PROP_SIZE); + pSpec->SetStartPoint(cFCOName(_T("/etc"))); + pAttr->SetName(_T("/etc")); + pAttr->SetSeverity(53); + + report.AddSpec(0x00020001, pSpec, pAttr); // TODO:bam - change these + cFCOReportSpecIter it(report, 0x00020001); // to use cFS::Genre + it.GetAddedSet()->Insert(addedFCO); + it.GetRemovedSet()->Insert(removedFCO); + report.AddChangedFCO(it, oldChangedFCO, newChangedFCO, changedPropVector); + + //Store the time taken to generate the test report: + time_finish = time(dummy_arg); + //report.SetCreationTime( (int64)difftime(time_finish, time_begin)); + //d.TraceDebug("Report calculation time = %I64i seconds.\n", report.GetCreationTime()); + + d.TraceDebug("Before serializing report:\n"); + TraceReport(report, d); + { + cFileArchive outFile; + outFile.OpenReadWrite(_T("tmp.twr")); + cSerializerImpl outSer(outFile, cSerializerImpl::S_WRITE); + + outSer.Init(); + outSer.WriteObject(&report); + outSer.Finit(); + + outFile.Close(); + + cFileArchive inFile; + inFile.OpenRead(_T("tmp.twr")); + cSerializerImpl inSer(inFile, cSerializerImpl::S_READ); + + cFCOReport inReport; + + inSer.Init(); + inSer.ReadObject(&inReport); + inSer.Finit(); + + d.TraceDebug("Read in serialized report:\n"); + TraceReport(inReport, d); + } + } + + // TODO -- test cFCOReportSpecIter::Remove() + // TODO -- test cFCOReportChangeIter::Remove() + d.TraceDebug("*** We still need to test Remove() for the two iterator classes!\n"); + + pSpec->Release(); + pAttr->Release(); + addedFCO->Release(); + removedFCO->Release(); + changedFCO->Release(); + oldChangedFCO->Release(); + newChangedFCO->Release(); + + d.TraceDebug("Leaving...\n"); + return; +} + diff --git a/src/tw/fcoreportutil.cpp b/src/tw/fcoreportutil.cpp new file mode 100644 index 0000000..bab28a2 --- /dev/null +++ b/src/tw/fcoreportutil.cpp @@ -0,0 +1,157 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoreportutil.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdtw.h" +#include + +#include "fcoreportutil.h" +#include "fcoreport.h" +#include "core/debug.h" +#include "core/fsservices.h" +#include "tw/fcoreport.h" +#include "fco/fcodatasource.h" +#include "fco/iterproxy.h" +#include "fco/fco.h" +#include "headerinfo.h" +#include "core/timeconvert.h" +#include "fco/twfactory.h" +#include "fco/fcopropdisplayer.h" +#include "twutil.h" + +//============================================================================= +// class cFCOReportUtil +//============================================================================= + +void cFCOReportUtil::CalculateHeaderInfo( + cFCOReportHeader& reportHeader, + const TSTRING& policyFilename, + const TSTRING& configFilename, + const TSTRING& dbFilename, + const TSTRING& commandLineParams, + int64 createTime, + int64 lastDBUpdateTime + ) +{ + reportHeader.SetPolicyFilename(policyFilename); + reportHeader.SetConfigFilename(configFilename); + reportHeader.SetDBFilename(dbFilename); + reportHeader.SetSystemName(cTWUtil::GetSystemName()); + reportHeader.SetCommandLineParams(commandLineParams); + reportHeader.SetIPAddress(cTWUtil::GetIPAddress()); + reportHeader.SetCreator(cTWUtil::GetCurrentUser()); + reportHeader.SetHostID(cTWUtil::GetHostID()); + reportHeader.SetCreationTime(createTime); + reportHeader.SetLastDBUpdateTime(lastDBUpdateTime); +} + +void cFCOReportUtil::FinalizeReport( cFCOReport& rr ) +{ + cFCOReportGenreIter genreIter( rr ); + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) + { + InitPropDisplayer( genreIter ); + } +} + +void cFCOReportUtil::InitPropDisplayer( cFCOReportGenreIter& gi ) +{ + if(gi.GetGenreHeader().GetPropDisplayer() == NULL) + gi.GetGenreHeader().SetPropDisplayer(iTWFactory::GetInstance()->CreatePropDisplayer()); + + iFCOPropDisplayer* pPropDisplayer = gi.GetGenreHeader().GetPropDisplayer(); + ASSERT( pPropDisplayer != 0); + + // cycle through all FCOs in report + // TODO: make a FCO iter class in fcoreport.cpp + cFCOReportSpecIter ri( gi ); + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + // + // added + // + + // get added set + const iFCOSet* pAddedSet = ri.GetAddedSet(); + ASSERT( pAddedSet != 0); + + // get fco iterator + proxy iter + const cIterProxy pSetIterAdded = pAddedSet->GetIter(); + ASSERT( pSetIterAdded != 0); + + // iterate over all fcos + for( pSetIterAdded->SeekBegin(); !pSetIterAdded->Done(); pSetIterAdded->Next() ) + { + pPropDisplayer->InitForFCO( pSetIterAdded->FCO() ); + } + + // + // removed + // + + // get removed set + const iFCOSet* pRemovedSet = ri.GetRemovedSet(); + ASSERT( pRemovedSet != 0); + + // get fco iterator + proxy iter + const cIterProxy pSetIterRemoved = pRemovedSet->GetIter(); + ASSERT( pSetIterRemoved != 0); + + // iterate over all fcos + for( pSetIterRemoved->SeekBegin(); !pSetIterRemoved->Done(); pSetIterRemoved->Next() ) + { + pPropDisplayer->InitForFCO( pSetIterRemoved->FCO() ); + } + + // + // changed + // + + // get changed set iterator (don't need pointer to changed set, just need spec iter) + cFCOReportChangeIter changedIter( ri ); + + // iterate over all changed fcos + for( changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next() ) + { + // we've already have old FCO info from db + pPropDisplayer->InitForFCO( changedIter.GetNew() ); + } + } +} + + diff --git a/src/tw/fcoreportutil.h b/src/tw/fcoreportutil.h new file mode 100644 index 0000000..b4e2510 --- /dev/null +++ b/src/tw/fcoreportutil.h @@ -0,0 +1,76 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fcoreportutil.h +// +// class cFCOReportUtil -- utility functions for the tripwire report class +// + +#ifndef __FCOREPORTUTIL_H +#define __FCOREPORTUTIL_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +class cFCOReport; +class cFCOReportHeader; +class cFCOReportGenreIter; + +class cFCOReportUtil +{ +public: + static void CalculateHeaderInfo( + cFCOReportHeader& reportHeader, + const TSTRING& policyFilename, + const TSTRING& configFilename, + const TSTRING& dbFilename, + const TSTRING& commandLineParams, + int64 createTime, + int64 lastDBUpdateTime + ); + + static void FinalizeReport( cFCOReport& rr ); + // call this when you're done adding to the report. + // adds any info propDisplayer needs, and adds info to header + +private: + static void InitPropDisplayer( cFCOReportGenreIter& gi ); + // call this to gather any info from machine that the report will need for displaying FCOs +}; + +#endif //__FCOREPORTUTIL_H + diff --git a/src/tw/filemanipulator.cpp b/src/tw/filemanipulator.cpp new file mode 100644 index 0000000..f79e6de --- /dev/null +++ b/src/tw/filemanipulator.cpp @@ -0,0 +1,357 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// filemanipulator.cpp -- Provides functionality to examine tripwire file headers +// for file type and encryption type. Also provides a mechanism for +// changing encryption keys or removing encryption. +// + +#include "stdtw.h" +#include "filemanipulator.h" +#include "core/serializerimpl.h" +#include "twutil.h" +#include "fcodatabasefile.h" +#include "fcoreport.h" +#include "configfile.h" +#include "policyfile.h" +#include "headerinfo.h" +#include "core/usernotify.h" +#include "twcrypto/crypto.h" +#include "util/fileutil.h" +#include "tw/twstrings.h" +#include "core/displayencoder.h" + +//============================================================================= +// class cFileManipulator +//============================================================================= + +cFileManipulator::cFileManipulator(const TCHAR* filename) +{ + mbInit = false; + mFileName = filename; +} + +cFileManipulator::cFileManipulator(const cFileManipulator& rhs) +: mFileName(rhs.mFileName), + mFileHeader(rhs.mFileHeader) +{ +} + +cFileManipulator::~cFileManipulator() +{ +} + +void cFileManipulator::Init() +{ + if (cFileUtil::FileExists(mFileName)) + { + cFileArchive arch; + try + { + try + { + arch.OpenRead( mFileName.c_str() ); + } + catch (eArchive&) + { + throw eFileManipFileRead( mFileName ); + } + + cSerializerImpl s(arch, cSerializerImpl::S_READ); + mFileHeader.Read(&s); + } + catch (eArchive&) + { + throw eFileManipHeaderNotFound( mFileName ); + } + catch (eSerializer&) + { + throw eFileManipHeaderNotFound( mFileName ); + } + } + else + { + throw eFileManipFileNotFound( mFileName ); + } + mbInit = true; +} + +const cFileHeaderID* cFileManipulator::GetHeaderID() +{ + ASSERT( mbInit ); + if (!mbInit) + { +// return NULL; + Init(); + } + return &mFileHeader.GetID(); +} + +uint32 cFileManipulator::GetFileVersion() +{ + ASSERT( mbInit ); + if (!mbInit) + { +// return 0; + Init(); + } + return mFileHeader.GetVersion(); +} + +cFileHeader::Encoding cFileManipulator::GetEncoding() +{ + ASSERT( mbInit ); + if (!mbInit) + { +// return (cFileHeader::Encoding)0; + Init(); + } + return mFileHeader.GetEncoding(); +} + +// Try to decrypt the file using the given key. If thorough is true then +// the entire file is read into memory. Returns true if decryption was +// successful. +bool cFileManipulator::TestDecryption(const cElGamalSigPublicKey& key, bool thorough) +{ + // TODO: pay attention to thorough flag. For now we will just always act thoroughly. + + ASSERT( mbInit ); + if (!mbInit) + { + return false; + } + + bool fError = false; + + // "turn down" the verbosity of iUserNotify to V_NORMAL it it is V_VERBOSE to make output a little cleaner + bool fChangedVerbosity = false; + int savedVerbosity = iUserNotify::GetInstance()->GetVerboseLevel(); + if( savedVerbosity == iUserNotify::V_VERBOSE ) + { + iUserNotify::GetInstance()->SetVerboseLevel( iUserNotify::V_NORMAL ); + fChangedVerbosity = true; + } + + try + { + if (mFileHeader.GetID() == cFCODatabaseFile::GetFileHeaderID()) + { + cFCODatabaseFile db; + bool encrypted; + cTWUtil::ReadDatabase(mFileName.c_str(), db, &key, encrypted); + } + else if (mFileHeader.GetID() == cFCOReport::GetFileHeaderID()) + { + cFCOReport rep; + cFCOReportHeader reph; + bool encrypted; + cTWUtil::ReadReport(mFileName.c_str(), reph, rep, &key, true, encrypted); + } + else if (mFileHeader.GetID() == cConfigFile::GetFileHeaderID()) + { + // read the embedded key from config file and see if it is the same + // as the public key passed in. + cMemoryArchive memArch; + TSTRING configText; //not used + cTWUtil::ReadConfigText( mFileName.c_str(), configText, &memArch ); + memArch.Seek( 0, cBidirArchive::BEGINNING ); + + // only do the test if there is baggage (indicating the cfg file is encrypted) + if( memArch.Length() > 0 ) + { + // create the two public keys... + cElGamalSigPublicKey pubKey( memArch.GetMemory() ); + + // compare the two .... + if( ! pubKey.IsEqual( key ) ) + throw ePoly(); + } + } + else if (mFileHeader.GetID() == cPolicyFile::GetFileHeaderID()) + { + std::string policyText; + cTWUtil::ReadPolicyText(mFileName.c_str(), policyText, &key); + } + else + throw ePoly(); + } + catch (eError&) + { + fError = true; + } + + // reset verbosity + if( fChangedVerbosity ) + iUserNotify::GetInstance()->SetVerboseLevel( savedVerbosity ); + + return( fError == false ); +} + +// Change the encryption on a file. +// If pNewKey is NULL, then encryption on the file will be removed. +// If pOldKey is NULL and the file is currently encrypted, then the +// function will throw eFileManip; +// If pOldKey is not NULL and the file is encrypted, then the fuction +// will throw eFileManip; +// If pOldKey is NULL and pNewKey is NULL and the file is not +// currently encrypted, the function will not do anything and will just +// return. +// Returns on successful encryption change. +void cFileManipulator::ChangeEncryption(const cElGamalSigPublicKey* pOldKey, const cElGamalSigPrivateKey* pNewKey, bool backup) +{ + ASSERT( mbInit ); + if (!mbInit) + { + Init(); + } + + // check the pOldKey matches the current encryption state + if (mFileHeader.GetEncoding() != cFileHeader::ASYM_ENCRYPTION) + { + if (pOldKey != NULL) + throw eFileManipNotEncrypted( mFileName ); + if (pNewKey == NULL) + return; // NOOP + } + else if (pOldKey == NULL) + throw eFileManipMissingKey(); + + if (!cFileUtil::FileWritable(mFileName)) + throw eFileManipNotWritable( mFileName ); + + if (mFileHeader.GetID() == cFCODatabaseFile::GetFileHeaderID()) + { + cFCODatabaseFile db; + bool encrypted; + + cTWUtil::ReadDatabase(mFileName.c_str(), db, pOldKey, encrypted); + if (backup) + { + TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension(); + iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str()); + } + + cTWUtil::WriteDatabase(mFileName.c_str(), db, pNewKey != NULL, pNewKey); + return; + } + else if (mFileHeader.GetID() == cFCOReport::GetFileHeaderID()) + { + cFCOReport rep; + cFCOReportHeader reph; + bool encrypted; + cTWUtil::ReadReport(mFileName.c_str(), reph, rep, pOldKey, false, encrypted); + if (backup) + { + TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension(); + iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str()); + } + cTWUtil::WriteReport(mFileName.c_str(), reph, rep, pNewKey != NULL, pNewKey); + return; + } + else if (mFileHeader.GetID() == cConfigFile::GetFileHeaderID()) + { + TSTRING configText; + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_CONFIG_FILE).c_str(), + cDisplayEncoder::EncodeInline( mFileName ).c_str()); + + cTWUtil::ReadConfigText(mFileName.c_str(), configText); + if (backup) + { + TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension(); + iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str()); + } + + cTWUtil::WriteConfigText(mFileName.c_str(), configText, pNewKey != NULL, pNewKey); + + return; + } + else if (mFileHeader.GetID() == cPolicyFile::GetFileHeaderID()) + { + std::string policyText; + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_POLICY_FILE).c_str(), + cDisplayEncoder::EncodeInline( mFileName ).c_str()); + + cTWUtil::ReadPolicyText(mFileName.c_str(), policyText, pOldKey); + if (backup) + { + TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension(); + iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str()); + } + + cTWUtil::WritePolicyText(mFileName.c_str(), policyText, pNewKey != NULL, pNewKey); + + return; + } + +} + +// method for getting a list of manipulators +// returns number of files matched +int cFileManipulator::LoadFiles(std::list& ret, TSTRING mask) +{ + ret.clear(); + + // TODO: we need to be able to deal with masks for the NT version. + // Right now *.* will not work in NT. We should not get a '*' for unix. + + try + { + ret.push_back(cFileManipulator(mask.c_str())); + } + catch (eError&) + { + // file does not exist + return 0; + } + + return 1; +} + +bool cFileManipulator::UseSiteKey(const cFileHeaderID& headerID) +{ + if (headerID == cFCODatabaseFile::GetFileHeaderID() || + headerID == cFCOReport::GetFileHeaderID()) + return false; + else + if (headerID == cConfigFile::GetFileHeaderID() || + headerID == cPolicyFile::GetFileHeaderID()) + return true; + + ASSERT(false); // what could it be? be careful not to en/decrypt keyfiles. + return false; +} + diff --git a/src/tw/filemanipulator.h b/src/tw/filemanipulator.h new file mode 100644 index 0000000..4dae2b8 --- /dev/null +++ b/src/tw/filemanipulator.h @@ -0,0 +1,142 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// filemanipulator.h -- Provides functionality to examine tripwire file headers +// for file type and encryption type. Also provides a mechanism for +// changing encryption keys or removing encryption. +// + +#ifndef __FILEMANIPULATOR_H +#define __FILEMANIPULATOR_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __FILEHEADER_H +#include "core/fileheader.h" +#endif + +class cElGamalSigPublicKey; +class cElGamalSigPrivateKey; + +/* +class eFileManipulator : public eError +{ +public: + eFileManipulator(int errorNum, TSTRING filename); + ~eFileManipulator(); + + virtual TSTRING GetMsg() const; +}; + enum ErrorNum + { + ERR_FILE_MANIPULATOR_INVALID_FILE = 2300, + ERR_LAST + }; + + TSTRING eFileManipulator::GetMsg() const + { + TSTRING ret = iUserString::GetInstance()->GetString(STR_ERROR_FILENAME); + ret.append(mMsg); + return ret; + } +*/ + +//============================================================================= +// eFileManip +//============================================================================= +TSS_FILE_EXCEPTION( eFileManip, eFileError ) +TSS_FILE_EXCEPTION( eFileManipInvalidFile, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipFileRead, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipHeaderNotFound,eFileManip ) +TSS_FILE_EXCEPTION( eFileManipFileNotFound, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipNotEncrypted, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipMissingKey, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipNotWritable, eFileManip ) +TSS_FILE_EXCEPTION( eFileManipUnrecognizedFileType, eFileManip ) + +//============================================================================= +// cFileManipulator +//============================================================================= +class cFileManipulator +{ +public: + cFileManipulator(const TCHAR* filename); + // throws eArchive if file does not exist + cFileManipulator(const cFileManipulator& rhs); + ~cFileManipulator(); + void Init(); + + // information for this file + TSTRING GetFileName() const; + const cFileHeaderID* GetHeaderID() ; // returns NULL if error code is non-zero + uint32 GetFileVersion() ; // throws eFileManipulator if error code is non-zero + cFileHeader::Encoding GetEncoding() ; // throws eFileManipulator if error code is non-zero + + // things you can do to this file + bool TestDecryption(const cElGamalSigPublicKey& key, bool thorough) ; + // Try to decrypt the file using the given key. If thorough is true then + // the entire file is read into memory. Returns true if decryption was + // successful. + // throws eFileManipulator if error code is non-zero + void ChangeEncryption(const cElGamalSigPublicKey* pOldKey, const cElGamalSigPrivateKey* pNewKey, bool backup); + // Change the encryption on a file. + // If pNewKey is NULL, then encryption on the file will be removed. + // If pOldKey is NULL and the file is currently encrypted, then the + // function will throw an exception; + // If pOldKey is not NULL and the file is encrypted, then the fuction + // will throw an exception; + // If pOldKey is NULL and pNewKey is NULL and the file is not + // currently encrypted, the function will not do anything and will just + // return. + + // utility functions + static int LoadFiles(std::list& ret, TSTRING mask); + // method for getting a list of manipulators + // returns number of files matched, or zero if no files matched mask passed + static bool UseSiteKey(const cFileHeaderID& headerID); + // convenience function that returns true if header is a config file or policy file + // and returns false if it is a database or report. + +private: + bool mbInit; + TSTRING mFileName; + cFileHeader mFileHeader; +}; + +inline TSTRING cFileManipulator::GetFileName() const +{ + return mFileName; +} +#endif + diff --git a/src/tw/headerinfo.cpp b/src/tw/headerinfo.cpp new file mode 100644 index 0000000..e4d98b5 --- /dev/null +++ b/src/tw/headerinfo.cpp @@ -0,0 +1,179 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////////////// +//headerinfo.cpp : implementation for base class that stores and returns info. +// for database and report header objects. + +#include "stdtw.h" +#include "headerinfo.h" +#include "core/debug.h" +#include "core/serializer.h" +#include "fco/fcopropdisplayer.h" +#include "core/errorutil.h" + +IMPLEMENT_TYPEDSERIALIZABLE( cHeaderInfo, _T("cHeaderInfo"), 0, 1 ); +IMPLEMENT_TYPEDSERIALIZABLE( cFCODbHeader, _T("cFCODbHeader"), 0, 1 ); +IMPLEMENT_TYPEDSERIALIZABLE( cFCOReportHeader, _T("cFCOReportHeader"), 0, 1 ); + +IMPLEMENT_TYPEDSERIALIZABLE( cGenreHeaderInfo, _T("cGenreHeaderInfo"), 0, 1 ); +IMPLEMENT_TYPEDSERIALIZABLE( cFCODbGenreHeader, _T("cFCODbGenreHeader"), 0, 1 ); +IMPLEMENT_TYPEDSERIALIZABLE( cFCOReportGenreHeader, _T("cFCOReportGenreHeader"),0, 1 ); + + + +////////////////////////////////////////////////////////////////////////////// +// Ctor, Dtor: Ctor intializes the Header data to zero or a NULL equivalent. +cHeaderInfo::cHeaderInfo() +{ + Clear(); +} + +cHeaderInfo::~cHeaderInfo() +{ +} + + +void cHeaderInfo::Clear() +{ + tstr_SystemName = _T(""); + tstr_PolicyFilename= _T(""); + tstr_ConfigFilename= _T(""); + tstr_DBFilename= _T(""); + tstr_CommandLineParams= _T(""); + tstr_CreatedBy= _T(""); + tstr_IPAddress= _T(""); + tstr_HostID = _T(""); + i64_CreationTime = 0; + i64_LastDBUpdateTime = 0; +} + + +void cHeaderInfo::Read ( iSerializer* pSerializer, int32 version ) // throw (eSerializer, eArchive) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("cHeaderInfo Read"))); + + pSerializer->ReadString( tstr_SystemName ); + pSerializer->ReadString( tstr_PolicyFilename ); + pSerializer->ReadString( tstr_ConfigFilename ); + pSerializer->ReadString( tstr_DBFilename ); + pSerializer->ReadString( tstr_CommandLineParams ); + pSerializer->ReadString( tstr_CreatedBy ); + pSerializer->ReadString( tstr_IPAddress ); + pSerializer->ReadString( tstr_HostID ); + pSerializer->ReadInt64( i64_CreationTime ); + pSerializer->ReadInt64( i64_LastDBUpdateTime ); +} + + +void cHeaderInfo::Write(iSerializer* pSerializer) const // throw (eSerializer, eArchive) +{ + pSerializer->WriteString( tstr_SystemName ); + pSerializer->WriteString( tstr_PolicyFilename ); + pSerializer->WriteString( tstr_ConfigFilename ); + pSerializer->WriteString( tstr_DBFilename ); + pSerializer->WriteString( tstr_CommandLineParams ); + pSerializer->WriteString( tstr_CreatedBy ); + pSerializer->WriteString( tstr_IPAddress ); + pSerializer->WriteString( tstr_HostID ); + pSerializer->WriteInt64( i64_CreationTime ); + pSerializer->WriteInt64( i64_LastDBUpdateTime ); +} + + + +////////////////////////////////////////////////////////////////////////////// +// Ctor, Dtor: Ctor intializes the Header data to zero or a NULL equivalent. +cGenreHeaderInfo::cGenreHeaderInfo() + : mpPropDisplayer( 0 ), + i32_ObjectsScanned( 0 ) +{ +} + +cGenreHeaderInfo::~cGenreHeaderInfo() +{ + delete mpPropDisplayer; +} + +cGenreHeaderInfo::cGenreHeaderInfo( const cGenreHeaderInfo& rhs ) + : mpPropDisplayer(0) +{ + if( this == &rhs ) + return; + + if( rhs.mpPropDisplayer ) + mpPropDisplayer = rhs.GetPropDisplayer()->Clone(); + + i32_ObjectsScanned = rhs.GetObjectsScanned(); +} + +void cGenreHeaderInfo::Clear() +{ + delete mpPropDisplayer; + mpPropDisplayer = 0; + i32_ObjectsScanned = 0; +} + +void cGenreHeaderInfo::Read ( iSerializer* pSerializer, int32 version ) // throw (eSerializer, eArchive) +{ + if (version > Version()) + ThrowAndAssert(eSerializerVersionMismatch(_T("cHeaderInfo Read"))); + + // read the prop displayer + ASSERT( mpPropDisplayer == 0); + + int32 fMakePD; + pSerializer->ReadInt32( fMakePD ); + + if( fMakePD == 1 ) + mpPropDisplayer = static_cast( pSerializer->ReadObjectDynCreate() ); + + pSerializer->ReadInt32( i32_ObjectsScanned ); +} + + +void cGenreHeaderInfo::Write(iSerializer* pSerializer) const // throw (eSerializer, eArchive) +{ + // write out the prop displayer + if( mpPropDisplayer ) + { + pSerializer->WriteInt32(1); + pSerializer->WriteObjectDynCreate( mpPropDisplayer ); + } + else + pSerializer->WriteInt32(0); + + pSerializer->WriteInt32( i32_ObjectsScanned ); +} + + + diff --git a/src/tw/headerinfo.h b/src/tw/headerinfo.h new file mode 100644 index 0000000..aa2bb94 --- /dev/null +++ b/src/tw/headerinfo.h @@ -0,0 +1,226 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//headerinfo.h : a base class for database and report header objects. +#ifndef __HEADERINFO_H +#define __HEADERINFO_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __TYPES_H +#include "core/types.h" +#endif +#ifndef __SERIALIZABLE_H +#include "core/serializable.h" +#endif + +class iFCOPropDisplayer; + +/////////////////////////////////////////////////////////////////////////////// +// cHeaderInfo +/////////////////////////////////////////////////////////////////////////////// +class cHeaderInfo : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cHeaderInfo(); + virtual ~cHeaderInfo(); + virtual void Clear(); + //Clears all data in a header to 0 or NULL equivalents. + + //Functions for getting & setting header values: + const TSTRING& GetPolicyFilename() const; + const TSTRING& GetConfigFilename() const; + const TSTRING& GetDBFilename() const; + const TSTRING& GetSystemName() const; + const TSTRING& GetCommandLineParams() const; + const TSTRING& GetIPAddress() const; + const TSTRING& GetCreator() const; + const TSTRING& GetHostID() const; + int64 GetCreationTime() const; + int64 GetLastDBUpdateTime() const; + //Set: + void SetPolicyFilename( const TSTRING& ); + void SetConfigFilename( const TSTRING& ); + void SetDBFilename( const TSTRING& ); + void SetSystemName( const TSTRING& ); + void SetCommandLineParams( const TSTRING& ); + void SetIPAddress( const TSTRING& ); + void SetCreator( const TSTRING& ); + void SetHostID( const TSTRING& ); + void SetCreationTime( int64 ); + void SetLastDBUpdateTime( int64 ); + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) + +private: + cHeaderInfo& operator=( cHeaderInfo& ); + + //Header Data: + TSTRING tstr_PolicyFilename; + TSTRING tstr_ConfigFilename; + TSTRING tstr_DBFilename; + TSTRING tstr_SystemName; + TSTRING tstr_CommandLineParams; + TSTRING tstr_IPAddress; + TSTRING tstr_CreatedBy; + TSTRING tstr_HostID; + int64 i64_CreationTime; + mutable int64 i64_LastDBUpdateTime; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cGenreHeaderInfo -- for genres +/////////////////////////////////////////////////////////////////////////////// +class cGenreHeaderInfo : public iTypedSerializable +{ + DECLARE_TYPEDSERIALIZABLE() + +public: + cGenreHeaderInfo(); + cGenreHeaderInfo( const cGenreHeaderInfo& ); + virtual ~cGenreHeaderInfo(); + + void Clear(); + + // the prop displayer ... once this is set, this object owns the destruction of it. + void SetPropDisplayer(iFCOPropDisplayer* pPropDisplayer); + iFCOPropDisplayer* GetPropDisplayer(); + const iFCOPropDisplayer* GetPropDisplayer() const; + + void SetObjectsScanned( int32 ); + int32 GetObjectsScanned() const; + + // iSerializable interface + virtual void Read (iSerializer* pSerializer, int32 version = 0); // throw (eSerializer, eArchive) + virtual void Write(iSerializer* pSerializer) const; // throw (eSerializer, eArchive) +private: + cGenreHeaderInfo& operator=( cGenreHeaderInfo& ); + + iFCOPropDisplayer* mpPropDisplayer; + int32 i32_ObjectsScanned; +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCODbGenreHeader -- for database genres +// TODO -- once this actually has data, move it to a seperate file +/////////////////////////////////////////////////////////////////////////////// +class cFCODbGenreHeader : public cGenreHeaderInfo +{ + DECLARE_TYPEDSERIALIZABLE() +public: + cFCODbGenreHeader() {}; + cFCODbGenreHeader( const cFCODbGenreHeader& rhs ) : cGenreHeaderInfo( rhs ) {}; +private: + cFCODbGenreHeader& operator=( cFCODbGenreHeader& ); +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOReportGenreHeader -- for report genres +// TODO -- once this actually has data, move it to a seperate file +/////////////////////////////////////////////////////////////////////////////// +class cFCOReportGenreHeader : public cGenreHeaderInfo +{ +public: + cFCOReportGenreHeader() {}; + cFCOReportGenreHeader( const cFCOReportGenreHeader& rhs ) : cGenreHeaderInfo( rhs ) {}; + DECLARE_TYPEDSERIALIZABLE() +private: + cFCOReportGenreHeader& operator=( cFCOReportGenreHeader& ); +}; + + + +/////////////////////////////////////////////////////////////////////////////// +// cFCODbHeader -- specialization of header info for databases +// TODO -- once this actually has data, move it to a seperate file +/////////////////////////////////////////////////////////////////////////////// +class cFCODbHeader : public cHeaderInfo +{ + DECLARE_TYPEDSERIALIZABLE() +public: + typedef cHeaderInfo inherited; +private: + cFCODbHeader& operator=( cFCODbHeader& ); +}; + +/////////////////////////////////////////////////////////////////////////////// +// cFCOReportHeader -- specialization of header info for reports +// TODO -- once this actually has data, move it to a seperate file +/////////////////////////////////////////////////////////////////////////////// +class cFCOReportHeader : public cHeaderInfo +{ + typedef cHeaderInfo inherited; + DECLARE_TYPEDSERIALIZABLE() +private: + cFCOReportHeader& operator=( cFCOReportHeader& ); +}; + + +//----------------------------------------------------------------------------- +// inline implementation +//----------------------------------------------------------------------------- + +inline const TSTRING& cHeaderInfo::GetPolicyFilename() const { return tstr_PolicyFilename; }; +inline const TSTRING& cHeaderInfo::GetConfigFilename() const { return tstr_ConfigFilename; }; +inline const TSTRING& cHeaderInfo::GetDBFilename() const { return tstr_DBFilename; }; +inline const TSTRING& cHeaderInfo::GetSystemName() const { return tstr_SystemName; }; +inline const TSTRING& cHeaderInfo::GetCommandLineParams() const { return tstr_CommandLineParams; }; +inline const TSTRING& cHeaderInfo::GetCreator() const { return tstr_CreatedBy; }; +inline const TSTRING& cHeaderInfo::GetIPAddress() const { return tstr_IPAddress; }; +inline const TSTRING& cHeaderInfo::GetHostID() const { return tstr_HostID; }; +inline int64 cHeaderInfo::GetCreationTime() const { return i64_CreationTime; }; +inline int64 cHeaderInfo::GetLastDBUpdateTime() const { return i64_LastDBUpdateTime; }; + +inline void cHeaderInfo::SetPolicyFilename( const TSTRING& tstr ) { tstr_PolicyFilename = tstr; }; +inline void cHeaderInfo::SetConfigFilename( const TSTRING& tstr ) { tstr_ConfigFilename = tstr; }; +inline void cHeaderInfo::SetDBFilename( const TSTRING& tstr ) { tstr_DBFilename = tstr; }; +inline void cHeaderInfo::SetSystemName( const TSTRING& name ) { tstr_SystemName = name; }; +inline void cHeaderInfo::SetCommandLineParams( const TSTRING& tstr ) { tstr_CommandLineParams = tstr; }; +inline void cHeaderInfo::SetCreator( const TSTRING& tstr ) { tstr_CreatedBy = tstr; }; +inline void cHeaderInfo::SetHostID( const TSTRING& tstr ) { tstr_HostID = tstr; }; +inline void cHeaderInfo::SetIPAddress( const TSTRING& tstr ) { tstr_IPAddress = tstr; }; +inline void cHeaderInfo::SetCreationTime( int64 i ) { i64_CreationTime = i; }; +inline void cHeaderInfo::SetLastDBUpdateTime( int64 i ) { i64_LastDBUpdateTime = i; }; + +inline void cGenreHeaderInfo::SetPropDisplayer(iFCOPropDisplayer* pPropDisplayer) { mpPropDisplayer = pPropDisplayer; } +inline iFCOPropDisplayer* cGenreHeaderInfo::GetPropDisplayer() { return mpPropDisplayer; } +inline const iFCOPropDisplayer* cGenreHeaderInfo::GetPropDisplayer() const { return mpPropDisplayer; } +inline void cGenreHeaderInfo::SetObjectsScanned( int32 i ) { i32_ObjectsScanned = i; }; +inline int32 cGenreHeaderInfo::GetObjectsScanned() const { return i32_ObjectsScanned; }; + + +#endif //__HEADERINFO_H + diff --git a/src/tw/policyfile.cpp b/src/tw/policyfile.cpp new file mode 100644 index 0000000..9fc16c8 --- /dev/null +++ b/src/tw/policyfile.cpp @@ -0,0 +1,63 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// policyfile.cpp +// + +#include "stdtw.h" +#include "policyfile.h" +#include "core/tchar.h" +#include "core/fileheader.h" + +/////////////////////////////////////////////////////////////////////////////// +// GetFileHeaderID() +/////////////////////////////////////////////////////////////////////////////// + +struct cPolicyFileFHID { + cFileHeaderID* policyID; + + cPolicyFileFHID() { policyID = 0; } + ~cPolicyFileFHID() { delete policyID; } +} gPolicyFileFHID; + +const cFileHeaderID& cPolicyFile::GetFileHeaderID() +{ + if (gPolicyFileFHID.policyID == 0) + gPolicyFileFHID.policyID = new cFileHeaderID(_T("cPolicyFile")); + + // sanity check + ASSERT(*gPolicyFileFHID.policyID == cFileHeaderID(_T("cPolicyFile"))); + + return *gPolicyFileFHID.policyID; +} + + diff --git a/src/tw/policyfile.h b/src/tw/policyfile.h new file mode 100644 index 0000000..9ed08f7 --- /dev/null +++ b/src/tw/policyfile.h @@ -0,0 +1,57 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// policyfile.h +// + +#ifndef __POLICYFILE_H +#define __POLICYFILE_H + +//#ifndef __TYPED_H +//#include "typed.h" +//#endif + +class cFileHeaderID; + +class cPolicyFile //: public iTyped +{ +public: + cPolicyFile(); + virtual ~cPolicyFile(); + + static const cFileHeaderID& GetFileHeaderID(); + +private: +}; + +#endif + diff --git a/src/tw/stdtw.cpp b/src/tw/stdtw.cpp new file mode 100644 index 0000000..7111d82 --- /dev/null +++ b/src/tw/stdtw.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtw.cpp +// Date....: 5/12/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtw.h" + +// eof: stdtw.cpp diff --git a/src/tw/stdtw.h b/src/tw/stdtw.h new file mode 100644 index 0000000..e7a5a92 --- /dev/null +++ b/src/tw/stdtw.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtw.h +// +// Standard includes for tw +// + +#include "core/stdcore.h" + diff --git a/src/tw/systeminfo.cpp b/src/tw/systeminfo.cpp new file mode 100644 index 0000000..43654f6 --- /dev/null +++ b/src/tw/systeminfo.cpp @@ -0,0 +1,44 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// systeminfo.cpp +// + +#include "stdtw.h" +#include "systeminfo.h" + +TSTRING cSystemInfo::mExePath(_T("")); +bool cSystemInfo::mbExePathSet(false); +TSTRING cSystemInfo::mExeDir(_T("")); +bool cSystemInfo::mbExeDirSet(false); +int64 cSystemInfo::mExecuteStartTime(0); + diff --git a/src/tw/systeminfo.h b/src/tw/systeminfo.h new file mode 100644 index 0000000..c3f41cb --- /dev/null +++ b/src/tw/systeminfo.h @@ -0,0 +1,126 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// systeminfo.h +// +// cSystemInfo -- a storage place for run time system information +#ifndef __SYSTEMINFO_H +#define __SYSTEMINFO_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __DEBUG_H +#include "core/debug.h" +#endif + +class cSystemInfo +{ +public: + cSystemInfo(); + ~cSystemInfo(); + + static TSTRING GetExePath(); + static void SetExePath(const TSTRING& path); + // Get the full path to this executable + + static TSTRING GetExeDir(); + static void SetExeDir(const TSTRING& dir); + // these methods get and set the executable's working directory ... it is asserted + // that SetExeDir() has been called when GetExeDir() is called. + + static int64 GetExeStartTime(); + static void SetExeStartTime(const int64& time); + // Get and set the approximate time (time_t format) which the excecutable was started. + // This will be used for all times having to do with this run of the executable. + +private: + static TSTRING mExePath; + static bool mbExePathSet; + static TSTRING mExeDir; + static bool mbExeDirSet; + static int64 mExecuteStartTime; +}; + +//----------------------------------------------------------------------------- +// inline implementation +//----------------------------------------------------------------------------- +inline cSystemInfo::cSystemInfo() +{ +} + +inline cSystemInfo::~cSystemInfo() +{ +} + +inline TSTRING cSystemInfo::GetExePath() +{ + ASSERT( mbExePathSet ); + return mExePath; +} + +inline void cSystemInfo::SetExePath(const TSTRING& path) +{ + ASSERT( ! path.empty() ); + mbExePathSet = true; + + mExePath = path; +} + +inline TSTRING cSystemInfo::GetExeDir() +{ + ASSERT( mbExeDirSet ); + return mExeDir; +} + +inline void cSystemInfo::SetExeDir(const TSTRING& dir) +{ + ASSERT( ! dir.empty() ); + mbExeDirSet = true; + + mExeDir = dir; +} + +inline int64 cSystemInfo::GetExeStartTime() +{ + ASSERT( mExecuteStartTime != 0 ); + return mExecuteStartTime; +} + +inline void cSystemInfo::SetExeStartTime(const int64& time) +{ + mExecuteStartTime = time; +} + +#endif //__SYSTEMINFO_H + diff --git a/src/tw/textdbviewer.cpp b/src/tw/textdbviewer.cpp new file mode 100644 index 0000000..432baef --- /dev/null +++ b/src/tw/textdbviewer.cpp @@ -0,0 +1,539 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// textdbviewer.cpp -- implementation for dbviewer class +// + +//========================================================================= +// DIRECTIVES +//========================================================================= + + +//========================================================================= +// INCLUDES +//========================================================================= +#include "stdtw.h" + +#include +#include + +#include "core/tchar.h" +#include "textdbviewer.h" +#include "core/debug.h" +#include "fcodatabasefile.h" +#include "dbdatasource.h" +#include "fco/fcospec.h" +#include "fco/iterproxy.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" +#include "core/fsservices.h" +#include "fco/fcospecattr.h" +#include "core/timeconvert.h" +#include "fco/fcopropdisplayer.h" +#include "headerinfo.h" +#include "fco/genreswitcher.h" +#include "core/twlocale.h" +#include "fco/twfactory.h" +#include "fco/fconametranslator.h" +#include "fco/fcoundefprop.h" +#include "tw/twstrings.h" +#include "core/displayencoder.h" + +//========================================================================= +// USING NAMESPACE +//========================================================================= + +using namespace std; + +//========================================================================= +// GLOBALS +//========================================================================= + +static const TCHAR* g_sz79Dashes = _T("-------------------------------------------------------------------------------"); +static const TCHAR* g_sz79Equals = _T("==============================================================================="); + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= +static void InitOStream( TOSTREAM* pOut ); +static void DisplayFCOProps( const iFCO* const pFCO, const iFCOPropDisplayer* pPD, TOSTREAM* pOut ); + +static void OutputDatabaseHeader ( const cFCODbHeader& dbHeader, TOSTREAM* pOut ); +// Currently we don't have a rule summary. See function definition below +//static void OutputRulesSummary ( const cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut ); + + +static void OutputSectionDelimiter( int nString, TOSTREAM* pOut ); +static void OutputGenreDelimiter( cGenre::Genre g, TOSTREAM* pOut ); + +static void OutputObjectSummary( cFCODatabaseFile& rd, TOSTREAM* pOut, int margin ); +static void OutputObjectDetail( cFCODatabaseFile& rd, TOSTREAM* pOut ); + +static void OutputObjectSummary( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin ); +static void OutputObjectDetail( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut ); + + +static void OutputIterChildren ( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails ); +static void OutputIterPeers ( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails ); +//static void OutputIter ( cDbDataSourceIter& dbIter, const iFCOPropDisplayer* pPD, TOSTREAM* pOut, bool fDetails ); +static void PrintFCOShort ( const iFCO* pFCO, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin ); +//static void OutputSpecHeader( const cFCODbSpecIter& dbi, TOSTREAM* pOut ); +//static void OutputDetailHeader( const cFCODbSpecIter& dbi, int nObjects, TOSTREAM* pOut ); + +static TSTRING util_Encode( const TSTRING& sIn ) +{ + static cDisplayEncoder e; + TSTRING sOut = sIn; + e.Encode( sOut ); + return sOut; +} + +//========================================================================= +// METHOD CODE +//========================================================================= + +void cTextDBViewer::PrintDB( cFCODatabaseFile& rd, const TSTRING& strFilename ) +{ + TOSTREAM* pOut; + TOFSTREAM fileOut; + bool fIsFile = false; + + if( strFilename == _T("-") ) + { + pOut = &TCOUT; + } + else + { + //Gonna have to insert a lame hack here, since ostr.open DEMANDS a const char*!! +#ifdef _UNICODE + char ncBuf[ iFSServices::TW_MAX_PATH ]; + wcstombs( ncBuf, strFilename.c_str(), sizeof(char)); + fileOut.open( ncBuf ); +#else //narrow character mode + fileOut.open( strFilename.c_str() ); +#endif + + if( fileOut.is_open() ) + { + pOut = &fileOut; + fIsFile = true; + } + else + { + ASSERT( false ); + throw eArchiveOpen( strFilename, iFSServices::GetInstance()->GetErrString() ); + } + } + + InitOStream( pOut ); + + // + // output header, just like it sez.... + // + OutputDatabaseHeader( rd.GetHeader(), pOut ); + + OutputObjectSummary( rd, pOut, DETAILS_MARGIN ); + + OutputObjectDetail( rd, pOut ); + + + // we're done + (*pOut) << g_sz79Dashes << endl; + (*pOut) << TSS_GetString( cTW, tw::STR_END_OF_DB ) << endl << endl; + (*pOut) << TSS_GetString( cTW, tw::STR_COPYRIGHT ) << endl; + + if( fIsFile ) + static_cast(pOut)->close(); + + return; +} + + +/////////////////////////////////////////////////////////////////////////////// +// OutputFCO +/////////////////////////////////////////////////////////////////////////////// +void cTextDBViewer::OutputFCO( cDbDataSourceIter& dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails ) +{ + InitOStream( pOut ); + + if( dbIter.HasFCOData() ) + { + iFCO* pFCO = dbIter.CreateFCO(); + + if( fDetails ) + { + (*pOut) << TSS_GetString( cTW, tw::STR_OBJECT_NAME ) << _T(" ") << pNT->ToStringDisplay( pFCO->GetName() ).c_str() << endl << endl; + DisplayFCOProps( pFCO, pPD, pOut ); + (*pOut) << endl << endl; + } + else + PrintFCOShort( pFCO, pPD, pNT, pOut, DETAILS_MARGIN ); + + pFCO->Release(); + } +} + + +//========================================================================= +// UTIL FUNCTION CODE +//========================================================================= + +void InitOStream( TOSTREAM* pOut ) +{ + // align left + (*pOut).flags( ( (*pOut).flags() & ~std::ios::adjustfield ) | std::ios::left ); +} + +/////////////////////////////////////////////////////////////////////////////// +// PrintFCOShort +/////////////////////////////////////////////////////////////////////////////// +static void PrintFCOShort( const iFCO* pFCO, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin ) +{ + ASSERT( pOut != 0); + + TSTRING strDetails; + + // + // output ""\n\t
" + // + (*pOut) << _T(" "); + (*pOut) << pNT->ToStringDisplay( pFCO->GetName() ).c_str(); + (*pOut) << endl; + (*pOut) << setw( margin ) << _T(""); + pPD->GetDetails( pFCO, strDetails ); + (*pOut) << strDetails; + (*pOut) << _T("\n"); +} + + +static void OutputIterChildren( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails ) +{ + dbIter.Descend(); + OutputIterPeers( dbIter, pPD, pNT, pOut, fDetails ); +} + +static void OutputIterPeers( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails ) +{ + for ( dbIter.SeekBegin(); ! dbIter.Done(); dbIter.Next() ) + { + // TODO: this obviously needs to be expanded upon. + cTextDBViewer::OutputFCO( dbIter, pPD, pNT, pOut, fDetails ); + + if( dbIter.CanDescend() ) + OutputIterChildren( dbIter, pPD, pNT, pOut, fDetails ); + } +} + + +static void OutputDatabaseHeader( const cFCODbHeader& dbHeader, TOSTREAM* pOut ) +{ + const int headerColumnWidth = 30; + (*pOut) << TSS_GetString( cTW, tw::STR_DBPRINT_TITLE ) << endl << endl; + + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_DB_GENERATED_BY ) << util_Encode( dbHeader.GetCreator() ) << endl; + + TSTRING tstrDummy; + int64 i64CreateTime = dbHeader.GetCreationTime(); + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_DB_CREATED_ON ) << cTWLocale::FormatTime( i64CreateTime, tstrDummy ).c_str() << endl; + + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_DB_LAST_UPDATE ); + + int64 i64LastDBUTime = dbHeader.GetLastDBUpdateTime(); + if( i64LastDBUTime == 0 ) + { + (*pOut) << TSS_GetString( cTW, tw::STR_NEVER ) << endl << endl; + } + else + { + (*pOut) << cTWLocale::FormatTime( i64LastDBUTime, tstrDummy ).c_str() << endl << endl; + } + + OutputSectionDelimiter( tw::STR_DB_SUMMARY, pOut ); + + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_HOST_NAME ) << dbHeader.GetSystemName().c_str() << endl; + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_HOST_IP ) << dbHeader.GetIPAddress() << endl; + + +// only output host ID on UNIX systems +#if IS_UNIX + (*pOut).width(headerColumnWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_HOST_ID ); + + if(! dbHeader.GetHostID().empty() ) + (*pOut) << dbHeader.GetHostID() << endl; + else + (*pOut) << TSS_GetString( cTW, tw::STR_NONE ) << endl; +#endif + + (*pOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_POLICY_FILE_USED ) + << util_Encode( dbHeader.GetPolicyFilename() ) + << endl; + + (*pOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_CONFIG_FILE_USED ) + << util_Encode( dbHeader.GetConfigFilename() ) + << endl; + + (*pOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_DB_FILE_USED ) + << util_Encode( dbHeader.GetDBFilename() ) + << endl; + + (*pOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_CMD_LINE_USED ) + << util_Encode( dbHeader.GetCommandLineParams() ) + << endl + << endl; +} + +#if 0 +// The rules summary is not working due to changes in the databasse infrastructure. Until +// we hear different from the product manager, it is out of here. +static void OutputRulesSummary(const cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut ) +{ + const cHierDatabase& db = genreIter.GetDb(); + + // these should add up to 79 + const int nameWidth = 50; + const int numObjectsWidth = 10; + + (*pOut) << g_sz79Dashes << endl; + (*pOut) << TSS_GetString( cTW, tw::STR_RULE_SUMMARY ) << endl; + (*pOut) << g_sz79Dashes << endl << endl; + + (*pOut).width(nameWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_RULE_NAME ); + (*pOut).width(numObjectsWidth); + (*pOut) << TSS_GetString( cTW, tw::STR_OBJECTS ) << endl; + + (*pOut) << setw( nameWidth ) << _T("---------"); + (*pOut) << setw( numObjectsWidth ) << _T("-------"); + (*pOut) << endl; + + // output spec stats + cFCOSpecListCanonicalIter specIter( genreIter.GetSpecList() ); + + // iterate over all database elements + int nTotalObjects = 0; + for( specIter.SeekBegin(); !specIter.Done(); specIter.Next() ) + { + (*pOut) << setw( nameWidth ) << specIter.Spec()->GetName(); + + // if the name is too long, put it on its own line + if( specIter.Spec()->GetName().length() >= nameWidth ) + { + (*pOut) << endl; + + // output space holder + (*pOut).width(nameWidth); + (*pOut) << _T(""); + } + + (*pOut).width(numObjectsWidth); + (*pOut) << _T("TODO"); + //(*pOut) << specIter.GetFCOSet()->Size(); TODO: Do this right + (*pOut) << endl; + } + + (*pOut) << endl; + + // NOTE 4 Jan 99 mdb -- this used to use dbHeader.GetTotalObjectsScanned() but it was not always consistent with the + // total number of objects in the database. TODO -- if we are really not going to use this number, then we should + // not store it in the database at all. + // + (*pOut) << TSS_GetString( cTW, tw::STR_TOTAL_NUM_FILES ); + //(*pOut) << _T(" ") << nTotalObjects << endl; + (*pOut) << _T("TODO") << endl; + (*pOut) << endl; +} +#endif + + + +void OutputSectionDelimiter( int nString, TOSTREAM* pOut ) +{ + (*pOut) << g_sz79Equals << endl; + (*pOut) << TSS_GetString( cTW, nString ) << endl; + (*pOut) << g_sz79Equals << endl << endl; +} + +void OutputGenreDelimiter( cGenre::Genre g, TOSTREAM* pOut ) +{ + (*pOut) << g_sz79Dashes << endl; + (*pOut) << _T("# ") << TSS_GetString( cTW, tw::STR_SECTION ); + (*pOut) << _T(": ") << cGenreSwitcher::GetInstance()->GenreToString( g, true ) << endl; + (*pOut) << g_sz79Dashes << endl << endl; +} + +void OutputObjectSummary( cFCODatabaseFile& rd, TOSTREAM* pOut, int margin ) +{ + OutputSectionDelimiter( tw::STR_OBJECT_SUMMARY, pOut ); + + cFCODatabaseFileIter genreIter(rd); + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) + { + cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre) genreIter.GetGenre() ); + + iFCONameTranslator* pNT = iTWFactory::GetInstance()->GetNameTranslator(); + + OutputGenreDelimiter( (cGenre::Genre) genreIter.GetGenre(), pOut ); + + // Currently we don't have a rule summary. See function definition below + //OutputRulesSummary( genreIter, pNT, pOut); + + OutputObjectSummary( genreIter, pNT, pOut, margin ); + } +} + +void OutputObjectSummary( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin ) +{ + const cDbDataSourceIter dbIter( &genreIter.GetDb() ); + ASSERT(dbIter.AtRoot()); + + (*pOut) << setw( margin ) << _T(""); + TSTRING strBuf; + (*pOut) << genreIter.GetGenreHeader().GetPropDisplayer()->GetDetailsHeader( strBuf, margin ).c_str() << endl; + + OutputIterPeers( dbIter, genreIter.GetGenreHeader().GetPropDisplayer(), pNT, pOut, false ); + (*pOut) << endl; +} + + +void OutputObjectDetail( cFCODatabaseFile& rd, TOSTREAM* pOut ) +{ + OutputSectionDelimiter( tw::STR_OBJECT_DETAIL, pOut ); + + cFCODatabaseFileIter genreIter(rd); + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) + { + cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre) genreIter.GetGenre() ); + iFCONameTranslator* pNT = iTWFactory::GetInstance()->GetNameTranslator(); + + OutputGenreDelimiter( (cGenre::Genre) genreIter.GetGenre(), pOut ); + + OutputObjectDetail( genreIter, pNT, pOut ); + } +} + + +void OutputObjectDetail( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut ) +{ + const cDbDataSourceIter dbIterDetails(&genreIter.GetDb()); + + OutputIterPeers( dbIterDetails, genreIter.GetGenreHeader().GetPropDisplayer(), pNT, pOut, true); + (*pOut) << endl; +} + + +/* +static void OutputDetailHeader( const cFCODbSpecIter &dbi, int nObjects, TOSTREAM* pOut ) +{ + (*pOut) << g_sz79Dashes << _T( "\n" ); + (*pOut) << TSS_GetString( cTW, tw::STR_FILE_DETAIL ) << endl; + + TOSTRINGSTREAM ostr2; + ostr2 << TSS_GetString( cTW, tw::STR_RULE_NAME ) << _T(": ") << dbi.GetSpec()->GetName().c_str(); + ostr2 << _T( " (" ) << dbi.GetSpec()->GetStartPoint().AsString().c_str() << _T( ")" ) << endl; + (*pOut) << ostr2.str().c_str(); + + (*pOut) << TSS_GetString( cTW, tw::STR_TOTAL_NUM_FILES ) << _T(" ") << nObjects << endl; + + (*pOut) << g_sz79Dashes << endl << endl; +} +*/ + +/* +static void OutputSpecHeader( const cFCODbSpecIter &dbi, TOSTREAM* pOut ) +{ + (*pOut) << g_sz79Dashes << _T( "\n" ); + + TOSTRINGSTREAM ostr2; + ostr2 << TSS_GetString( cTW, tw::STR_RULE_NAME ) << _T(": ") << dbi.GetSpec()->GetName().c_str(); + ostr2 << _T( " (" ) << dbi.GetSpec()->GetStartPoint().AsString().c_str() << _T( ")" ) << endl; + (*pOut) << ostr2.str().c_str(); + + (*pOut) << g_sz79Dashes << _T( "\n" ); +} +*/ + + +void DisplayFCOProps( const iFCO* const pFCO, const iFCOPropDisplayer* pPD, TOSTREAM* pOut ) +{ + ASSERT( pOut != 0); + ASSERT( pFCO != 0); + + const int attrNameWidth = 24; + const int attrValueWidth = 28; + + // output header + // TODO: make these constants into enums + (*pOut).width( attrNameWidth ); + (*pOut) << TSS_GetString( cTW, tw::STR_ATTRIBUTES ); + (*pOut).width( attrValueWidth ); + (*pOut) << TSS_GetString( cTW, tw::STR_ATTR_VALUE ); + (*pOut) << endl; + + (*pOut).width( attrNameWidth ); + (*pOut) << _T("-------------"); + (*pOut).width( attrValueWidth ); + (*pOut) << _T("-----------"); + (*pOut) << endl; + + int iNumProps = pFCO->GetPropSet()->GetNumProps(); + for( int j = 0; j < iNumProps; j++ ) + { + // output if prop is in FCO, and prop is not cFCOUndefinedProp + if( + pFCO->GetPropSet()->GetValidVector().ContainsItem( j ) + && + pFCO->GetPropSet()->GetPropAt( j )->GetType() != cFCOUndefinedProp::GetInstance()->GetType() + ) + { + TSTRING strProp; + + // output property name + (*pOut).width( attrNameWidth ); + (*pOut) << pFCO->GetPropSet()->GetPropName(j); + (*pOut).width( attrValueWidth ); + (*pOut) << pPD->PropAsString( pFCO, j, attrNameWidth, 0 ); + (*pOut) << _T("\n"); + } + } +} + diff --git a/src/tw/textdbviewer.h b/src/tw/textdbviewer.h new file mode 100644 index 0000000..6ee7dfd --- /dev/null +++ b/src/tw/textdbviewer.h @@ -0,0 +1,71 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// textdbviewer.h -- definitions for textreportviewer class +// + +#ifndef __TEXTDBVIEWER_H +#define __TEXTDBVIEWER_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +class cFCODatabaseFile; +class iFCO; +class cFCODbHeader; +class iFCOPropDisplayer; +class cDbDataSourceIter; +class iFCONameTranslator; + +class cTextDBViewer +{ +public: + + static void PrintDB( cFCODatabaseFile& rd, const TSTRING& strFilename ); // throw + + static void OutputFCO( cDbDataSourceIter& dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails = true ); + // prints to the given ostream a text representation of the FCO pointed at by the iter. Silently + // does nothing if(dbIter.Done()). +private: + // + // private enums + // + enum + { + DETAILS_MARGIN = 4 + }; +}; + +#endif // __TEXTDBVIEWER_H + + diff --git a/src/tw/textreportviewer.cpp b/src/tw/textreportviewer.cpp new file mode 100644 index 0000000..5414045 --- /dev/null +++ b/src/tw/textreportviewer.cpp @@ -0,0 +1,2020 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// textreportviewer.cpp -- implementation for textreportviewer class +// + +// TODO:BAM put strings into resources +// TODO:BAM add debug strings + +//========================================================================= +// DIRECTIVES +//========================================================================= + + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdtw.h" +#include "textreportviewer.h" +#include "core/errorbucketimpl.h" +#include "core/fsservices.h" +#include "core/timeconvert.h" +#include "core/msystem.h" +#include "core/twlocale.h" +#include "core/errortable.h" +#include "core/debug.h" +#include "core/errorutil.h" +#include "core/displayutil.h" +#include "core/fixedfilebuf.h" +#include "fco/fcospec.h" +#include "fco/iterproxy.h" +#include "fco/fconame.h" +#include "fco/fcopropvector.h" +#include "fco/fcopropset.h" +#include "fco/fcoprop.h" +#include "fco/fconametranslator.h" +#include "fco/fcoundefprop.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fcopropdisplayer.h" +#include "fco/fcospecattr.h" +#include "fco/fcoundefprop.h" +#include "core/stringutil.h" +#include "util/fileutil.h" +#include "headerinfo.h" +#include "fcoreport.h" +#include "twstrings.h" +#include "core/displayencoder.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include +#include +#include +#include +#ifdef HAVE_WCHAR_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +using namespace std; + +//========================================================================= +// GLOBALS +//========================================================================= + +static const TCHAR* g_sz79Dashes = _T("-------------------------------------------------------------------------------"); +static const TCHAR* g_sz40Dashes = _T("----------------------------------------"); +static const TCHAR* g_sz79Equals = _T("==============================================================================="); + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +static void OpenOutputFile( fixed_basic_ofstream& out, const TSTRING& strFile ); // throw( eTextReportViewer ) +static void OpenInputFile ( std::ifstream& out, const TSTRING& strFile ); // throw( eTextReportViewer ) +static bool PrintableProp( const iFCO* pfcoOld, const iFCO* pfcoNew, int j ); + +static bool SpecEmpty( const cFCOReportSpecIter& ri ); + +static TSTRING util_Encode( const TSTRING& sIn ) +{ + static cDisplayEncoder e; + TSTRING sOut = sIn; + e.Encode( sOut ); + return sOut; +} +//========================================================================= +// METHOD CODE +//========================================================================= + +cTextReportViewer::cTextReportViewer( const cFCOReportHeader& h, const cFCOReport& r ) +{ + Init( h, const_cast(r) ); // TODO:BAM -- hack to allow creation + // for updating (non-const report) and non-updating + // (const report) in one constructor format +} + +cTextReportViewer::cTextReportViewer( const cFCOReportHeader& h, cFCOReport& r ) +{ + Init( h, r ); +} + +int cTextReportViewer::Init( const cFCOReportHeader& h, cFCOReport& r ) +{ + mpHeader = &h; + mpReport = &r; + mpOut = NULL; + mpCurPD = NULL; + mpCurNT = NULL; + mfUpdate = false; + mMaxSeverityViolated = 0; + mNumberViolations = 0; + mErrorNum = 1; + mReportingLevel = FULL_REPORT; + mfGotNumbers = false; + mCurrentCharSize = 0; + return 0; +} + +cTextReportViewer::~cTextReportViewer() +{ + if( mfUpdate ) + { + for( GenreList::iterator i = mFCOsRemoveFromReport.begin(); i != mFCOsRemoveFromReport.end(); i++ ) + { + ASSERT( i->second != 0 ); + i->second->clear(); + delete i->second; + } + } +} + + +int cTextReportViewer::GetMaxSeverityViolated() +{ + if( ! mfGotNumbers ) + GetReportNumbers(); + + return mMaxSeverityViolated; +} + +int cTextReportViewer::GetNumberViolations() +{ + if( ! mfGotNumbers ) + GetReportNumbers(); + + return mNumberViolations; +} + +void cTextReportViewer::InitOStream() +{ + // align left + (*mpOut).flags( ( (*mpOut).flags() & ~std::ios::adjustfield ) | std::ios::left ); +} + +void cTextReportViewer::DisplayReportAndHaveUserUpdateIt( const TSTRING& edName, ReportingLevel level ) //throw (eFSServices) +{ + if (!CanUpdate()) + { + // We should not be calling this for classes derived from cTextReport that can't update + THROW_INTERNAL("textreportviewer.cpp"); + } + + ASSERT( ! edName.empty() ); + + // + // get temp filename in which to store user-readable report + // + TSTRING strTempFile; + iFSServices* pFSServices = iFSServices::GetInstance(); + ASSERT( pFSServices != 0 ); + + pFSServices->GetTempDirName( strTempFile ); + strTempFile += _T("twtempXXXXXX"); + pFSServices->MakeTempFilename( strTempFile ); + + // this try/catch ensures the temp file was removed... + try + { + // we are updating... + mfUpdate = true; + + // + // write report to the temp file. put checks beside each FCO entry. + // + PrintTextReport( strTempFile, level ); + + // + // find an appropriate editor and launch it on the temp file. the user + // can uncheck any item she doesn't want put back into the database. + // + LaunchEditorOnFile( strTempFile, edName ); + + // + // read report back in from the temp file and remove any unchecked entries from + // the report + // + ReadTextReport( strTempFile ); + + // + // remove unchecked elements from remove + // + RemoveFCOsFromReport(); + } + catch(...) + { + // delete the temp file, then rethrow + pFSServices->FileDelete( strTempFile ); + throw; + } + // + // delete temp file + // + pFSServices->FileDelete( strTempFile ); +} + +/////////////////////////////////////////////////////////////////////////////// +// PrintTextReport +// +// prints a text version of the passed in report to the passed in stream; the +// version that takes a file name is just a convenience function that calls the +// ostream version. '-' can be passed to signify stdout. +/////////////////////////////////////////////////////////////////////////////// +void cTextReportViewer::PrintTextReport( const TSTRING& strFilename, ReportingLevel level ) //throw (eTextReportViewer); +{ + mReportingLevel = level; + + if( strFilename.compare(_T("-")) == 0 ) + { + mpOut = &TCOUT; + OutputTextReport(); + } + else + { + fixed_basic_ofstream out; + OpenOutputFile( out, strFilename ); + mpOut = &out; + OutputTextReport(); + out.close(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PrintTextReport +/////////////////////////////////////////////////////////////////////////////// +void cTextReportViewer::PrintTextReport( TOSTREAM& ostr, ReportingLevel level ) +{ + mReportingLevel = level; + mpOut = &ostr; + OutputTextReport(); +} + + +void cTextReportViewer::GetReportNumbers() +{ + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // We need to at least get the max severity in this function + cFCOReportSpecIter ri( genreIter ); + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + if( !IgnoreThisSpec( ri.GetAttr() ) ) + { + int nAdded = ri.GetAddedSet()->Size(); + int nRemoved = ri.GetRemovedSet()->Size(); + int nChanged = ri.GetNumChanged(); + + if( nAdded || nRemoved || nChanged ) + { + // update the max severity + if( mMaxSeverityViolated < ri.GetAttr()->GetSeverity() ) + mMaxSeverityViolated = ri.GetAttr()->GetSeverity(); + + mNumberViolations += ( nAdded + nRemoved + nChanged ); + } + } + } + } + + mfGotNumbers = true; +} + +void cTextReportViewer::OutputTextReport() //throw (eTextReportViewer); +{ + ASSERT( mpOut != 0 ); + + InitOStream(); + + // + // count up total violations, max severity, etc. + // + GetReportNumbers(); + + // + // TODO: move this + // + if( SINGLE_LINE == mReportingLevel ) + { + (*mpOut) << SingleLineReport() << endl; + } + else if( PARSEABLE == mReportingLevel ) + { + OutputParseableReport(); + } + else if( SUMMARY_ONLY <= mReportingLevel ) + { + // + // output header, just like it sez.... + // + OutputReportHeader(); + + // + // output summary info + // + OutputRulesSummary(); + + // + // print names of rule-breakers + // + // don't print out object summary if in CONCISE_REPORT because + // the detailed report will look a lot like the summary. + // + if( CONCISE_REPORT != mReportingLevel ) + { + OutputObjectSummary(); + } + + if( CONCISE_REPORT <= mReportingLevel ) + { + // + // print details of rule-breakers + // + OutputObjectDetails(); + } + + // + // output any errors + // + PrintErrors(); + + // + // output footer + // + OutputFooter(); + } +} + +void cTextReportViewer::SetUpForNewGenre( const cFCOReportGenreIter& genreIter ) +{ + // + // set up prop displayer and name translator + // + mpCurPD = genreIter.GetGenreHeader().GetPropDisplayer(); + mpCurNT = cGenreSwitcher::GetInstance()->GetFactoryForGenre( genreIter.GetGenre() )->GetNameTranslator(); +} + +void cTextReportViewer::PrintErrors() +{ + // + // output header + // + OutputSectionDelimiter( tw::STR_ERROR_REPORT ); + + // + // output any errors from the report's general error queue + // + bool fAtLeastOneGeneralError = false; + cErrorQueueIter eqIter( *( mpReport->GetErrorQueue() ) ); + for( eqIter.SeekBegin(); !eqIter.Done(); eqIter.Next() ) + { + ReportError( eqIter ); + fAtLeastOneGeneralError = true; + } + + // separate general errors from genre errors + if( fAtLeastOneGeneralError ) + (*mpOut) << endl; + + // + // cycle through genres + // + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // + // set up prop displayer and name translator + // + SetUpForNewGenre( genreIter ); + + // + // report errors for genre + // + bool fFirstErrorInGenre = true; + cFCOReportSpecIter rsi( genreIter ); + for( rsi.SeekBegin(); !rsi.Done(); rsi.Next() ) + { + cErrorQueueIter eqIter( *( rsi.GetErrorQueue() ) ); + for( eqIter.SeekBegin(); !eqIter.Done(); eqIter.Next() ) + { + if( fFirstErrorInGenre ) + { + OutputGenreDelimiter( genreIter.GetGenre() ); + fFirstErrorInGenre = false; + } + + ReportError( eqIter ); + } + } + + // separate genre errors + if( ! fFirstErrorInGenre ) + (*mpOut) << endl; + } + + // + // if there were no errors, tell user + // + if( 1 == mErrorNum ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_REPORT_NO_ERRORS ) << endl << endl; + } +} + +void cTextReportViewer::OutputSectionDelimiter( int nString ) +{ + (*mpOut) << g_sz79Equals << endl; + (*mpOut) << TSS_GetString( cTW, nString ) << endl; + (*mpOut) << g_sz79Equals << endl << endl; +} + +void cTextReportViewer::OutputGenreDelimiter( cGenre::Genre g, bool fDenoteBallotSection ) +{ + (*mpOut) << g_sz79Dashes << endl; + + // a # denotes the ballot section + if( fDenoteBallotSection ) + (*mpOut) << _T("# "); + else + (*mpOut) << _T(" "); + + (*mpOut) << TSS_GetString( cTW, tw::STR_SECTION ); + (*mpOut) << _T(": ") << cGenreSwitcher::GetInstance()->GenreToString( g, true ) << endl; + (*mpOut) << g_sz79Dashes << endl << endl; +} + +void cTextReportViewer::OutputNumDetails( int nString, int nObjects ) +{ + (*mpOut) << _T(" ") << g_sz40Dashes << endl; + (*mpOut) << _T(" ") << TSS_GetString( cTW, nString ) << nObjects << endl; + (*mpOut) << _T(" ") << g_sz40Dashes << endl << endl; +} + +void cTextReportViewer::OutputObjectSummary() +{ + // + // check if we should output summary + // + if (!WantOutputObjectSummary()) + return; + + // + // output summary header + // + OutputSectionDelimiter( tw::STR_OBJECT_SUMMARY ); + + // + // cycle through genres + // + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // + // set up prop displayer and name translator + // + SetUpForNewGenre( genreIter ); + + // + // output genre delimiter + // + OutputGenreDelimiter( genreIter.GetGenre(), true ); + + // + // output object summary + // + OutputObjectSummary( genreIter ); + } +} + +void cTextReportViewer::OutputObjectSummary( const cFCOReportGenreIter& genreIter ) +{ + // iterate over all report elements (keyed by a spec), and save + // references to all added, removed, and changed FCOs. We do this + // because we want to group the FCOs by added, removed, and changed, + // not by spec. + + + // + // if we're updating, we need to save a list of names + // + FCOList* pFCONameList = NULL; + if( mfUpdate ) + pFCONameList = new FCOList; + + cFCOReportSpecIter ri( genreIter ); + bool violationReported = false; + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + // skip this spec if it's not one we care about for this report + if (IgnoreThisSpec(ri.GetAttr())) + continue; + + // + // output a spec header if it was violated + // + if( ! SpecEmpty( ri ) ) + { + violationReported = true; + + OutputSpecHeader( ri ); + (*mpOut) << endl; + + if( mfUpdate ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_ADD_X ) << endl; + (*mpOut) << endl; + } + + // + // output added set + // + OutputAddedSummary( ri, pFCONameList ); + + // + // output removed set + // + OutputRemovedSummary( ri, pFCONameList ); + + // + // output changed set + // + OutputChangedSummary( ri, pFCONameList ); + } + } + + if (violationReported == false) + { + // There are no violations for this section + (*mpOut) << TSS_GetString( cTW, tw::STR_NO_VIOLATIONS_IN_SECTION ) << endl << endl; + } + + // + // insert FCO list into master list + // + if( mfUpdate ) + mFCOsRemoveFromReport.insert( cTextReportViewer::GenreList::value_type( genreIter.GetGenre(), pFCONameList ) ); +} + +void cTextReportViewer::OutputObjectDetails() +{ + // + // check if we should output details + // + if (!WantOutputObjectDetails()) + return; + + // + // output detail header + // + OutputSectionDelimiter( tw::STR_OBJECT_DETAIL ); + + // + // cycle through genres + // + cFCOReportGenreIter genreIter( *mpReport ); + for(genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // + // set up prop displayer and name translator + // + SetUpForNewGenre( genreIter ); + + // + // output genre delimiter + // + OutputGenreDelimiter( genreIter.GetGenre() ); + + // + // output details + // + OutputObjectDetails( genreIter ); + } +} + +void cTextReportViewer::OutputObjectDetails( const cFCOReportGenreIter& genreIter ) +{ + // + // Now enumerate all changes + // + cFCOReportSpecIter ri( genreIter ); + bool violationReported = false; + + for(ri.SeekBegin() ; !ri.Done(); ri.Next() ) + { + // skip this spec if it's not one we care about for this report + if (IgnoreThisSpec(ri.GetAttr())) + continue; + + // + // output spec section header if there are changes + // + if( ! SpecEmpty( ri ) ) + { + violationReported = true; + + OutputSpecHeader( ri ); + + // + // output added set + // + OutputAddedDetails( ri ); + + // + // output removed set + // + OutputRemovedDetails( ri ); + + // + // output changed set + // + OutputChangedDetails( ri ); + } + } // enum change details + + if (violationReported == false) + { + // There are no violations for this section + (*mpOut) << TSS_GetString( cTW, tw::STR_NO_VIOLATIONS_IN_SECTION ) << endl << endl; + } +} + +void cTextReportViewer::OutputFooter() +{ + (*mpOut) << g_sz79Dashes << endl; + (*mpOut) << TSS_GetString( cTW, tw::STR_END_OF_REPORT ) << endl << endl; + (*mpOut) << TSS_GetString( cTW, tw::STR_COPYRIGHT ) << endl; +} + + +bool cTextReportViewer::LaunchEditorOnFile( const TSTRING& strFilename, const TSTRING& edName ) //throw (eTextReportViewer) +{ + bool fRanViewer = false; + TSTRING editor = edName; + + // make sure we can read from this file + cFileUtil::TestFileReadable( strFilename ); + +#if IS_UNIX + + + // editor is going to need terminal type, so tell msystem to include + // it in environment when it makes its system call. + le_set("TERM"); + le_set("DISPLAY"); // DISPLAY and HOME needed so we can launch X apps. X apps apparently check + le_set("HOME"); // a .xpermissions file in the users home dir + le_set("LANG"); // LANG allowed through in case any apps need + int systemRet = msystem( (char*) ( ( editor+ _T(' ') + strFilename ).c_str() ) ); + le_unset("LANG"); + le_unset("HOME"); + le_unset("DISPLAY"); + le_unset("TERM"); + + if( 0 == systemRet ) + { + fRanViewer = true; + } + else + { + //ASSERT( false ); + throw eTextReportViewerEditorLaunch( edName ); + } + +#endif //if IS_WIN32 + + return( fRanViewer ); +} + + +void cTextReportViewer::ReportError( const cErrorQueueIter& eqIter ) +{ + const int nWidth = 5; + + // output error number + TOSTRINGSTREAM ostr; + ostr << mErrorNum << _T("."); + (*mpOut).width( nWidth ); + (*mpOut) << ostr.str(); + + // output general error + (*mpOut) << cErrorTable::GetInstance()->Get( eqIter.GetError().GetID() )<< endl; + + // output specific error + (*mpOut).width( nWidth ); + (*mpOut) << _T(""); // this is here so the next output is 10 chars over + (*mpOut) << cDisplayUtil::FormatMultiLineString( + cDisplayEncoder::EncodeInlineAllowWS( + eqIter.GetError().GetMsg() ), nWidth, 0 ) << endl; + + + mErrorNum++; +} + +void cTextReportViewer::PrintBallotLine( const iFCO& FCO ) +{ + ASSERT( mpOut != 0 ); + + // + // output "[X] " + // + + if( mfUpdate ) //only have Xs for updating + { + (*mpOut) << _T("[x] "); // TODO: should this be in resources? + } + + TSTRING strEncoded = mpCurNT->ToStringDisplay( FCO.GetName(), true ); + (*mpOut) << strEncoded.c_str(); + + (*mpOut) << endl; +} + + +// looks for "\n[" and leaves the file pointer at the next character +// could be a problem if the ballot box is the first line in the file, then "\n[" +// wouldn't be encountered, only "[", so make sure that the ballots aren't +// on the first line +// returns false if finds "\n#" -- start of new genre +int cTextReportViewer::FindNextLineToken() +{ + // loop over chars until (1) EOF is hit, or (2) we find "\n[" or '\n#' + for( GetChar(); !mpIn->eof(); GetChar() ) + { + if( mCurrentChar[0] == '\n' ) + { + // we'll only compare to single byte chars + // so it's ok to use PeekChar() instead of our GetChar() + if( PeekChar() == '[' ) + { + return TOKEN_BALLOT_BOX; + } + else if( PeekChar() == '#' ) // start of new genre + { + return TOKEN_GENRE; + } + } + } + + return( TOKEN_EOF ); +} + +void cTextReportViewer::ReadTextReport( const TSTRING& strFilename ) //throw (eTextReportViewer) +{ + std::ifstream in; + OpenInputFile( in, strFilename ); + mpIn = ∈ + + // + // for each genre and ballot box in text report file + // + bool fMoreTokens = true; + FCOList* pCurList = NULL; + while( fMoreTokens ) + { + switch( FindNextLineToken() ) + { + case TOKEN_GENRE: + GetGenreInfo( &pCurList ); + break; + case TOKEN_BALLOT_BOX: + GetBallotInfo( pCurList ); + break; + case TOKEN_EOF: + fMoreTokens = false; + break; + default: + ASSERT( false ); + break; + } + } + + // + // close the file + // + in.close(); +} + + +void cTextReportViewer::GetGenreInfo( FCOList** ppCurList ) +{ + // + // identify genre + // + TSTRING strGenre = GetGenre(); + ASSERT( ! strGenre.empty() ); + cGenre::Genre g = cGenreSwitcher::GetInstance()->StringToGenre( strGenre.c_str() ); + if( cGenre::GENRE_INVALID == g) + { + throw eTextReportViewerReportCorrupt(); // TODO: ERR_UKNOWN_GENRE + } + cGenreSwitcher::GetInstance()->SelectGenre( g ); + + // + // get list of fcos in report for this genre + // + GenreList::iterator curIter = mFCOsRemoveFromReport.find( g ); + if( curIter == mFCOsRemoveFromReport.end() ) + throw eTextReportViewerReportCorrupt(); // TODO: ERR_UKNOWN_GENRE + *ppCurList = curIter->second; + + // + // get the prop displayer + // + mpCurPD = cGenreSwitcher::GetInstance()->GetFactoryForGenre( g )->CreatePropDisplayer(); + mpCurNT = cGenreSwitcher::GetInstance()->GetFactoryForGenre( g )->GetNameTranslator(); +} + +void cTextReportViewer::GetBallotInfo( FCOList* pCurList ) +{ + if( ! pCurList ) + throw eTextReportViewerReportCorrupt(); + + // if the box is checked, then the user elected to leave the item + // in the report, so we do nothing. If the box isn't checked, then + // we must remove the item from the report. + if( IsChecked() ) + { + // + // look at the ballot line and get the name of the FCO + // + cFCOName fcoName; + GetFCONameFromBallotLine( fcoName ); + + /////////////////////////////////////// + // remove this FCO from list + cTextReportViewer::FCOList::const_iterator iter; + iter = pCurList->find( fcoName ); + if( iter == pCurList->end() ) + { + throw eTextReportViewerReportCorrupt();// TODO: ERR_UKNOWN_NAME + } + + pCurList->erase( fcoName ); + /////////////////////////////////////// + } +} + +// reads input up to EOL or EOF +TSTRING cTextReportViewer::GetGenre() +{ + std::string strGenre; + + EatSection(); + + while( true ) + { + char chFirst = PeekChar(); + if( PeekIsEOF() || + chFirst == '\r' || + chFirst == '\n' ) + break; + + // eat up char + GetChar(); + AppendChar( strGenre ); + } + + return cStringUtil::StrToTstr( strGenre ); +} + + +bool cTextReportViewer::PeekIsEOF() +{ + return( mpIn->peek() == char_traits::eof() ); +} + +// if the next character in the stream is ('X' or 'x'), it eats the x, else it returns false +// if the next character after the x is ']', it eats that, else it returns false. +bool cTextReportViewer::IsChecked() +{ + bool fIsChecked = false; + char chFirst; + + GetChar(); // eat up '[' + chFirst = PeekChar(); // look for 'X' + + if( ( ! PeekIsEOF() ) && + ( chFirst == 'X' || chFirst == 'x' ) ) // TODO: X in resources? + { + mpIn->get( chFirst ); // eat up X + + char chSecond = PeekChar(); + if( ( ! PeekIsEOF() ) && + ( chSecond == ']' ) ) + { + fIsChecked = true; + mpIn->get( chSecond ); // eat up ']' + } + } + + return( fIsChecked ); +} + +// FCO names are '\"' delimited and begin after the first '\"' after the ballot box +// NOTE: will not eat up a return character +void cTextReportViewer::GetFCONameFromBallotLine( cFCOName& fcoName ) //throw (eTextReportViewer) +{ + char chIn; + std::string strFCOName; + + #define TW_IS_QUOTE( ch ) ( ch == '\"' ) + #define TW_IS_EOL( ch ) ( ch == '\n' || ch == '\r' ) + #define TW_IS_BACKSLASH( ch ) ( ch == '\\' ) + + // + // go past any character that's not '\"' or EOL + // if we hit EOL, then there was no fconame present, so error + // + for( chIn = PeekChar(); + ! PeekIsEOF(); + chIn = PeekChar() ) // while not EOF + { + if( TW_IS_QUOTE( chIn ) ) + { + mpIn->get( chIn ); // eat up all chars but EOL + strFCOName += chIn; // add quote to string + + // we've found our quote, break and get name + break; + } + else if( TW_IS_EOL( chIn ) ) + { + // if EOL, there was no name! + throw eTextReportViewerReportCorrupt(); + } + else + { + GetChar(); // eat up all chars but EOL + } + } + + // + // get FCO name (chars up until the next '') + // + for( chIn = PeekChar(); + ! PeekIsEOF(); + chIn = PeekChar() ) // while not EOF + { + if( TW_IS_EOL( chIn ) ) // if EOL, there was no ending quote! + { + // found end of fconame + break; + } + else + { + // add char to fco name + GetChar(); + AppendChar( strFCOName ); + } + } + + // make sure we've got a name + if( strFCOName.empty() + || + ! mpCurNT->DisplayStringToFCOName( + cStringUtil::StrToTstr( strFCOName ), + fcoName ) ) + { + throw eTextReportViewerReportCorrupt(); // TODO -- it might be nice to be able to specify what line of the report got corrupted + } +} + +void cTextReportViewer::RemoveFCOsFromReport() //throw (eTextReportViewer) +{ + // TODO: remove fconames from fcosToRemove when we find them in report, + // so we don't compare that fconame again. Watch out for messing + // with iters in the for, loops, though! That's why I didn't do + // it yet... (and I figure most users would only un-X a few items, + // in which case it is currently faster anyways...) + + + // + // iterate over all specs in report, then in each of the added, + // removed, and changed sets, lookup the FCOName and, if found, + // delete it + // + int nFCOsRemoved = 0; + + cFCOReportGenreIter rgi( *mpReport ); + for( rgi.SeekBegin(); !rgi.Done(); rgi.Next() ) + { + cTextReportViewer::GenreList::iterator currentList = mFCOsRemoveFromReport.find( rgi.GetGenre() ); + ASSERT( currentList != mFCOsRemoveFromReport.end() ); + cTextReportViewer::FCOList* pFCOList = currentList->second; + + cFCOReportSpecIter rsi( rgi ); + for( rsi.SeekBegin(); !rsi.Done(); rsi.Next() ) + { + // search added + const iFCOSet* pAddedSet = rsi.GetAddedSet(); + ASSERT( pAddedSet != 0 ); + + const iFCOIter* fcoIter = NULL; + cTextReportViewer::FCOList::iterator iter; + // + // see if any FCOs to remove are in this set + // + for( iter = pFCOList->begin(); iter != pFCOList->end(); iter++ ) + { + fcoIter = pAddedSet->Lookup( *iter ); + if( fcoIter ) + { + fcoIter->Remove(); + nFCOsRemoved++; + + fcoIter->DestroyIter(); + } + } + + // search removed + // get removed set + const iFCOSet* pRemovedSet = rsi.GetRemovedSet(); + ASSERT( pRemovedSet != 0 ); + + // + // see if any FCOs to remove are in this set + // + for( iter = pFCOList->begin(); iter != pFCOList->end(); iter++ ) + { + fcoIter = pRemovedSet->Lookup( *iter ); + if( fcoIter ) + { + fcoIter->Remove(); + nFCOsRemoved++; + + fcoIter->DestroyIter(); + } + } + + + for( iter = pFCOList->begin(); iter != pFCOList->end(); iter++ ) + { + // search changed + // get changed set iterator + cFCOReportChangeIter changedIter( rsi ); + + // iterate over all changed fcos + for( changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next() ) + { + cFCOName name = changedIter.GetOld()->GetName(); + + if( name.IsEqual( *iter ) ) + { + changedIter.Remove(); + nFCOsRemoved++; + } + } + } + } + } + + // + // count FCOs to remove + // + int nFCOsToRemove = 0; + cTextReportViewer::GenreList::const_iterator iter = mFCOsRemoveFromReport.begin(); + for( ; iter != mFCOsRemoveFromReport.end(); iter++ ) + nFCOsToRemove += iter->second->size(); + + if( nFCOsToRemove != nFCOsRemoved ) + { + // TODO -- maybe have a different enumeration for this? + throw eTextReportViewerReportCorrupt(); + } +} + +void cTextReportViewer::OutputReportHeader() +{ + if (!WantOutputReportHeader()) + return; + + const int headerColumnWidth = 30; + + (*mpOut) << TSS_GetString( cTW, tw::STR_REPORT_TITLE ) << endl << endl; + + + (*mpOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_R_GENERATED_BY ) + << util_Encode( mpHeader->GetCreator() ) + << endl; + + // TODO: ( start / end / elapsed ) time + TSTRING tstrDummy; + int64 i64CreateTime = mpHeader->GetCreationTime(); + (*mpOut).width(headerColumnWidth); + (*mpOut) << TSS_GetString( cTW, tw::STR_R_CREATED_ON ) << cTWLocale::FormatTime( i64CreateTime, tstrDummy ).c_str() << endl; + + (*mpOut).width(headerColumnWidth); + (*mpOut) << TSS_GetString( cTW, tw::STR_DB_LAST_UPDATE ); + + int64 i64LastDBUTime = mpHeader->GetLastDBUpdateTime(); + if( i64LastDBUTime == 0 ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_NEVER ) << endl << endl; + } + else + { + (*mpOut) << cTWLocale::FormatTime( i64LastDBUTime, tstrDummy ).c_str() << endl << endl; + } + + OutputSectionDelimiter( tw::STR_R_SUMMARY ); + + (*mpOut).width(headerColumnWidth); + (*mpOut) << TSS_GetString( cTW, tw::STR_HOST_NAME ) << mpHeader->GetSystemName().c_str() << endl; + (*mpOut).width(headerColumnWidth); + (*mpOut) << TSS_GetString( cTW, tw::STR_HOST_IP ) << mpHeader->GetIPAddress() << endl; + +// only output host ID on UNIX systems +#if IS_UNIX + (*mpOut).width(headerColumnWidth); + (*mpOut) << TSS_GetString( cTW, tw::STR_HOST_ID ); + + if(! mpHeader->GetHostID().empty() ) + (*mpOut) << mpHeader->GetHostID() << endl; + else + (*mpOut) << TSS_GetString( cTW, tw::STR_NONE ) << endl; +#endif + + + (*mpOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_POLICY_FILE_USED ) + << util_Encode( mpHeader->GetPolicyFilename() ) + << endl; + + (*mpOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_CONFIG_FILE_USED ) + << util_Encode( mpHeader->GetConfigFilename() ) + << endl; + + (*mpOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_DB_FILE_USED ) + << util_Encode( mpHeader->GetDBFilename() ) + << endl; + + (*mpOut) << setw(headerColumnWidth) + << TSS_GetString( cTW, tw::STR_CMD_LINE_USED ) + << util_Encode( mpHeader->GetCommandLineParams() ) + << endl + << endl; +} + +void cTextReportViewer::OutputRulesSummary() +{ + // + // check if we should output summary + // + if( !WantOutputRulesSummary() ) + return; + + // + // output summary header + // + OutputSectionDelimiter( tw::STR_RULE_SUMMARY ); + + // + // cycle through genres + // + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // + // set up prop displayer and name translator + // + SetUpForNewGenre( genreIter ); + + // + // output genre delimiter + // + OutputGenreDelimiter( genreIter.GetGenre() ); + + // + // output rules summary + // + OutputRulesSummary( genreIter ); + } +} + +void cTextReportViewer::OutputRulesSummary( const cFCOReportGenreIter& genreIter ) +{ + // output spec stats header + // 2 + specNameWidth + severityWidth + 3*numObjectsWidth should be < 80 + const int specNameWidth = 32; + const int severityWidth = 18; + const int numObjectsWidth = 9; + (*mpOut) << _T(" "); // indent + (*mpOut).width( specNameWidth ); + (*mpOut) << TSS_GetString( cTW, tw::STR_RULE_NAME ); + (*mpOut).width( severityWidth ); + (*mpOut) << TSS_GetString( cTW, tw::STR_SEVERITY_LEVEL ); + (*mpOut).width( numObjectsWidth ); + (*mpOut) << TSS_GetString( cTW, tw::STR_ADDED ); + (*mpOut).width( numObjectsWidth ); + (*mpOut) << TSS_GetString( cTW, tw::STR_REMOVED ); + (*mpOut).width( numObjectsWidth ); + (*mpOut) << TSS_GetString( cTW, tw::STR_CHANGED ); + (*mpOut) << endl; + + (*mpOut) << _T(" "); + (*mpOut) << setw( specNameWidth ) << _T("---------"); + (*mpOut) << setw( severityWidth ) << _T("--------------"); + (*mpOut) << setw( numObjectsWidth ) << _T("-----"); + (*mpOut) << setw( numObjectsWidth ) << _T("-------"); + (*mpOut) << setw( numObjectsWidth ) << _T("--------"); + (*mpOut) << endl; + + // merge rules of duplicate names and severities + ObjectSummaryList summaryList; + CollateRulesSummary( genreIter, summaryList ); + + // Output the information in the list + int nTotalObjectsChanged = 0; + ObjectSummaryList::iterator si; + for (si = summaryList.begin(); si != summaryList.end(); ++si) + { + // highlight violated rules + if( si->mAddedObjects + si->mRemovedObjects + si->mChangedObjects > 0 ) + (*mpOut) << _T("* "); + else + (*mpOut) << _T(" "); // indent + + TSTRING strSpecName = util_Encode( si->mSpecName ); + (*mpOut) << setw( specNameWidth ) + << strSpecName; + + // if the name is too long, put it on its own line + if( strSpecName.length() >= (unsigned int)specNameWidth ) + { + (*mpOut) << endl; + (*mpOut) << _T(" "); // indent + (*mpOut).width( specNameWidth ); + (*mpOut) << _T(""); // output space holder + } + + (*mpOut).width( severityWidth ); + (*mpOut) << si->mSeverity; + (*mpOut).width( numObjectsWidth ); + (*mpOut) << si->mAddedObjects; + (*mpOut).width( numObjectsWidth ); + (*mpOut) << si->mRemovedObjects; + (*mpOut).width( numObjectsWidth ); + (*mpOut) << si->mChangedObjects; + (*mpOut) << endl; + + // output start point on next line + // TODO: I am not sure if I like this in the new collated reports, dmb Sept 16 1999 + if (!si->mStartPoint.empty()) + (*mpOut) << _T(" (") << si->mStartPoint << _T(")") << endl; + + nTotalObjectsChanged += si->mAddedObjects + si->mRemovedObjects + si->mChangedObjects; + } + + (*mpOut) << endl; + (*mpOut) << TSS_GetString( cTW, tw::STR_OBJECTS_SCANNED ) << _T(" ") << genreIter.GetGenreHeader().GetObjectsScanned() << endl; + (*mpOut) << TSS_GetString( cTW, tw::STR_TOTAL_VIOLATIONS ) << _T(" ") << nTotalObjectsChanged << endl; + (*mpOut) << endl; +} + + +void cTextReportViewer::CollateRulesSummary( const cFCOReportGenreIter& genreIter, ObjectSummaryList& summaryList ) +{ + summaryList.clear(); + + cFCOReportSpecIter ri( genreIter ); + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + // skip this spec if it's not one we care about for this report + if (IgnoreThisSpec(ri.GetAttr())) + continue; + + RuleSummaryLine newLine; + + newLine.mSpecName = util_Encode( ri.GetSpec()->GetName() ); + newLine.mSeverity = ri.GetAttr()->GetSeverity(); + newLine.mAddedObjects = ri.GetAddedSet()->Size(); + newLine.mRemovedObjects = ri.GetRemovedSet()->Size(); + newLine.mChangedObjects = ri.GetNumChanged(); + newLine.mStartPoint = mpCurNT->ToStringDisplay( ri.GetSpec()->GetStartPoint() ); + + // If there is already a summary line for this rule with equivalent severity, merge this one into it + ObjectSummaryList::iterator si; + for (si = summaryList.begin(); ; ++si) + { + if (si == summaryList.end()) + { + summaryList.push_back(newLine); + break; + } + + if (si->mSpecName.compare(newLine.mSpecName) == 0 && + si->mSeverity == newLine.mSeverity) + { + si->mAddedObjects += newLine.mAddedObjects; + si->mRemovedObjects += newLine.mRemovedObjects; + si->mChangedObjects += newLine.mChangedObjects; + + // if one of the start points is a subset of the other, then we take the shorter one. + // otherwise we set the startpoint to empty. + if (newLine.mStartPoint.length() <= si->mStartPoint.length()) + if (newLine.mStartPoint.compare(0, newLine.mStartPoint.length(), si->mStartPoint) == 0) + si->mStartPoint = newLine.mStartPoint; + else + si->mStartPoint.erase(); + else + if (si->mStartPoint.compare(0, si->mStartPoint.length(), newLine.mStartPoint) == 0) + ; + else + si->mStartPoint.erase(); + + break; + } + } + } +} + + +void cTextReportViewer::OutputSpecHeader( const cFCOReportSpecIter &ri ) +{ + if (!WantOutputSpecHeader()) + return; + + (*mpOut) << g_sz79Dashes << endl; + + (*mpOut) << TSS_GetString( cTW, tw::STR_RULE_NAME ) << _T(": ") << util_Encode( ri.GetSpec()->GetName() ); + (*mpOut) << _T( " (" ) << mpCurNT->ToStringDisplay( ri.GetSpec()->GetStartPoint() ) << _T( ")" ) << endl; + (*mpOut) << TSS_GetString( cTW, tw::STR_SEVERITY_LEVEL ) << _T(": ") << ri.GetAttr()->GetSeverity() << endl; + + (*mpOut) << g_sz79Dashes << endl; +} + +void cTextReportViewer::DisplayChangedProps( const iFCO* const pfcoOld, const iFCO* const pfcoNew, const cFCOPropVector* pv ) +{ + ASSERT( mpOut != 0 ); + ASSERT( pfcoOld || pfcoNew); // have to have at least one to display + + const iFCO* pfcoValid = pfcoOld ? pfcoOld : pfcoNew; // we need to use one of the pfco's for some Get functions + + // marginWidth + attrNameWidth + ( 2 * attrValueWidth ) should be < 80 + const int attrNameWidth = 21; + const int attrValueWidth = 28; + const int marginWidth = 2; // for " " or "* " + ASSERT( ( attrNameWidth + ( 2 * attrValueWidth ) + marginWidth ) < 80 ); + + // output header + (*mpOut) << setw( marginWidth ) << _T(""); + (*mpOut) << setw( attrNameWidth ) << TSS_GetString( cTW, tw::STR_ATTRIBUTES ); + (*mpOut) << setw( attrValueWidth ) << TSS_GetString( cTW, tw::STR_EXPECTED ); + (*mpOut) << setw( attrValueWidth ) << TSS_GetString( cTW, tw::STR_OBSERVED ); + (*mpOut) << endl; + + (*mpOut) << setw( marginWidth ) << _T(""); + (*mpOut) << setw( attrNameWidth ) << _T("-------------"); + (*mpOut) << setw( attrValueWidth ) << _T("-----------"); + (*mpOut) << setw( attrValueWidth ) << _T("-----------"); + (*mpOut) << endl; + + int iNumProps = pfcoValid->GetPropSet()->GetNumProps(); // TODO: what if new + old have different props + for( int j = 0; j < iNumProps; j++ ) + { + // if not a full report, only print properties that have changed + if( FULL_REPORT != mReportingLevel ) + { + if( !pv || !pv->ContainsItem( j ) ) + continue; + } + + // ignore certain combinations of undef and non-existent props + if( ! PrintableProp( pfcoOld, pfcoNew, j ) ) + continue; + + // highlight changes and set width for prop name + if( ! mpCurPD->IsMultiLineProp( j ) ) + { + if( !pv || pv->ContainsItem( j ) ) + (*mpOut) << setw( marginWidth ) << _T("*"); + else + (*mpOut) << setw( marginWidth ) << _T(""); + } + else // for multiline props we will highlight the observed prop if it has changed + { + (*mpOut) << setw( marginWidth ) << _T(""); + } + + + // + // output prop name + // + { + TSTRING strNewName; + strNewName = pfcoValid->GetPropSet()->GetPropName(j); + + if( mpCurPD->IsMultiLineProp( j ) ) + { + strNewName += _T(" ") ; + strNewName += TSS_GetString( cTW, tw::STR_EXPECTED ); + } + + //strNewName += _T(':') ; + + (*mpOut) << setw( attrNameWidth ) << strNewName; + } + + // + // output old value + // + TSTRING strOldValue; + (*mpOut).width( attrValueWidth ); + if( pfcoOld && pfcoOld->GetPropSet()->GetValidVector().ContainsItem( j ) ) + strOldValue = mpCurPD->PropAsString( pfcoOld, j, ( marginWidth + attrNameWidth ), 0 ).c_str(); + else + strOldValue = _T("---"); + (*mpOut) << strOldValue; + + + // + // output name again, if necessary (if multiline prop) + // + if( mpCurPD->IsMultiLineProp( j ) ) + { + TSTRING strNewName; + strNewName = pfcoValid->GetPropSet()->GetPropName(j); + strNewName += _T(" ") ; + strNewName += TSS_GetString( cTW, tw::STR_OBSERVED ); + //strNewName += _T(':') ; + + (*mpOut) << endl; + + if( !pv || pv->ContainsItem( j ) ) + (*mpOut) << setw( marginWidth ) << _T("*"); + else + (*mpOut) << setw( marginWidth ) << _T(""); + + (*mpOut) << setw( attrNameWidth ) << strNewName; + } + else + { + // if old value would run into this value, we need to put this value + // on the next line (but in the same column). don't output + // value but position "cursor" in the correct place + if( strOldValue.length() >= (unsigned int)attrValueWidth ) + { + (*mpOut) << endl; + (*mpOut) << setw( marginWidth ) << _T(""); + (*mpOut) << setw( attrNameWidth ) << _T(""); + (*mpOut) << setw( attrValueWidth ) << _T(""); + } + } + + // + // output new value + // + (*mpOut).width( attrValueWidth ); + if( pfcoNew && pfcoNew->GetPropSet()->GetValidVector().ContainsItem( j ) ) + (*mpOut) << mpCurPD->PropAsString( pfcoNew, j, ( marginWidth + attrNameWidth ), 0 ).c_str(); + else + (*mpOut) << _T("---"); + + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputAddedSummary( const cFCOReportSpecIter& ri, FCOList* pFCONameList ) +{ + if( ! ri.GetAddedSet()->IsEmpty() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_ADDED ) << _T(":") << endl; + + // iterate over all fcos + const cIterProxy pSetIterAdded = ri.GetAddedSet()->GetIter(); + for( pSetIterAdded->SeekBegin(); !pSetIterAdded->Done(); pSetIterAdded->Next() ) + { + PrintBallotLine( *pSetIterAdded->FCO() ); + + // if we're updating, save a list of FCO names + if( mfUpdate ) + pFCONameList->insert( pSetIterAdded->FCO()->GetName() ); + } + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputRemovedSummary( const cFCOReportSpecIter& ri, FCOList* pFCONameList) +{ + if( ! ri.GetRemovedSet()->IsEmpty() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_REMOVED ) << _T(":") << endl; + + // iterate over all fcos + const cIterProxy pSetIterRemoved = ri.GetRemovedSet()->GetIter(); + for( pSetIterRemoved->SeekBegin(); !pSetIterRemoved->Done(); pSetIterRemoved->Next() ) + { + PrintBallotLine( *pSetIterRemoved->FCO() ); + + // if we're updating, save a list of FCO names + if( mfUpdate ) + pFCONameList->insert( pSetIterRemoved->FCO()->GetName() ); + } + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputChangedSummary( const cFCOReportSpecIter& ri, FCOList* pFCONameList ) +{ + if( ri.GetNumChanged() > 0 ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_CHANGED ) << _T(":") << endl; + + // iterate over all changed fcos + cFCOReportChangeIter changedIter( ri ); + for( changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next() ) + { + PrintBallotLine( *changedIter.GetNew() ); + + // if we're updating, save a list of FCO names + if( mfUpdate ) + pFCONameList->insert( changedIter.GetNew()->GetName() ); + } + + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputAddedDetails( const cFCOReportSpecIter& ri ) +{ + if( ! ri.GetAddedSet()->IsEmpty() ) + { + OutputNumDetails( tw::STR_ADDED_FILES, ri.GetAddedSet()->Size() ); + + // iterate over all fcos + const cIterProxy pSetIterAdded = ri.GetAddedSet()->GetIter(); ASSERT( pSetIterAdded != 0 ); + for( pSetIterAdded->SeekBegin(); !pSetIterAdded->Done(); pSetIterAdded->Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_ADDED_FILE_NAME ) << _T(" ") << mpCurNT->ToStringDisplay( pSetIterAdded->FCO()->GetName() ).c_str() << endl; + + if( FULL_REPORT == mReportingLevel ) + { + (*mpOut) << endl; + DisplayChangedProps( NULL, pSetIterAdded->FCO(), NULL ); + (*mpOut) << endl << endl; + } + } + + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputRemovedDetails( const cFCOReportSpecIter& ri ) +{ + if( ! ri.GetRemovedSet()->IsEmpty() ) + { + OutputNumDetails( tw::STR_REMOVED_FILES, ri.GetRemovedSet()->Size() ); + + // iterate over all fcos + const cIterProxy pSetIterRemoved = ri.GetRemovedSet()->GetIter(); ASSERT( pSetIterRemoved != 0 ); + for( pSetIterRemoved->SeekBegin(); !pSetIterRemoved->Done(); pSetIterRemoved->Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_REMOVED_FILE_NAME ) << _T(" ") << mpCurNT->ToStringDisplay( pSetIterRemoved->FCO()->GetName() ).c_str() << endl; + + if( FULL_REPORT == mReportingLevel ) + { + (*mpOut) << endl; + DisplayChangedProps( pSetIterRemoved->FCO(), NULL, NULL ); + (*mpOut) << endl << endl; + } + } + (*mpOut) << endl; + } +} + +void cTextReportViewer::OutputChangedDetails( const cFCOReportSpecIter& ri ) +{ + if( ri.GetNumChanged() > 0 ) + { + OutputNumDetails( tw::STR_CHANGED_FILES, ri.GetNumChanged() ); + + // iterate over all changed fcos + cFCOReportChangeIter changedIter( ri ); + for( changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_CHANGED_FILE_NAME ) << _T(" ") << mpCurNT->ToStringDisplay( changedIter.GetOld()->GetName() ).c_str() << endl << endl; + DisplayChangedProps( changedIter.GetOld(), changedIter.GetNew(), &changedIter.GetChangeVector() ); + (*mpOut) << endl << endl; + } + (*mpOut) << endl; + } +} + +// overridables: +// These function allows derived classes to tailor reports +bool cTextReportViewer::IgnoreThisSpec(const cFCOSpecAttr *attr) { return false; } +bool cTextReportViewer::WantOutputReportHeader() { return true; } +bool cTextReportViewer::WantOutputRulesSummary() { return true; } +bool cTextReportViewer::WantOutputSpecHeader() { return true; } +bool cTextReportViewer::WantOutputObjectSummary() { return true; } +bool cTextReportViewer::WantOutputObjectDetails() { return true; } +bool cTextReportViewer::CanUpdate() { return true; } + + +//========================================================================= +// UTIL FUNCTION CODE +//========================================================================= + +void OpenInputFile( std::ifstream& in, const TSTRING& strFile ) // throw( eTextReportViewer ) +{ + in.open( cStringUtil::TstrToStr( strFile ).c_str() ); + + if(! in.is_open()) + { + throw eTextReportViewerFileOpen( strFile ); + } +} + +void OpenOutputFile( fixed_basic_ofstream& out, const TSTRING& strFile ) // throw( eTextReportViewer ) +{ + std::string narrowFilename = cStringUtil::TstrToStr( strFile ); + + // we explicitly create the file so that we control the + // permissions on the new file. + unlink(narrowFilename.c_str()); + int fd = open(narrowFilename.c_str(), O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 00600); + if (fd == -1 || close(fd) != 0) { + throw eTextReportViewerFileOpen( strFile ); + } + + out.open( narrowFilename.c_str() ); + + if(! out.is_open()) + throw eTextReportViewerFileOpen( strFile ); +} + +bool SpecEmpty( const cFCOReportSpecIter& ri ) +{ + return( ri.GetAddedSet()->IsEmpty() && ri.GetRemovedSet()->IsEmpty() && 0 == ri.GetNumChanged() ); +} + +bool PrintableProp( const iFCO* pfcoOld, const iFCO* pfcoNew, int j ) +{ + bool fOldExists = pfcoOld && pfcoOld->GetPropSet()->GetValidVector().ContainsItem( j ); + bool fNewExists = pfcoNew && pfcoNew->GetPropSet()->GetValidVector().ContainsItem( j ); + + // + // don't output line if neither FCO has the prop + // + if( ! fOldExists && ! fNewExists ) + { + return false; + } + + // + // don't output anything if both props are undefined + // + if ( fOldExists && fNewExists && + pfcoOld->GetPropSet()->GetPropAt( j )->GetType() + == cFCOUndefinedProp::GetInstance()->GetType() && + pfcoNew->GetPropSet()->GetPropAt( j )->GetType() + == cFCOUndefinedProp::GetInstance()->GetType() ) + { + return false; + } + + // + // don't output anything if old is undef and new doesn't exist + // + if( + fOldExists + && + ! fNewExists + && + pfcoOld->GetPropSet()->GetPropAt( j )->GetType() == cFCOUndefinedProp::GetInstance()->GetType() + ) + { + return false; + } + + // + // don't output anything if new is undef and old doesn't exist + // + if( + ! fOldExists + && + fNewExists + && + pfcoNew->GetPropSet()->GetPropAt( j )->GetType() == cFCOUndefinedProp::GetInstance()->GetType() + ) + { + return false; + } + + return true; +} + +void cTextReportViewer::EatSection() +{ + GetChar(); // get '#' + + // eat up " section: " + int nb = + cStringUtil::TstrToStr( + TSS_GetString( cTW, tw::STR_SECTION ) + ).length(); + + nb += 3; // one for each space surrounding section, and one for colon + + // eat up nb bytes + for( int i = 0; !mpIn->eof() && i < nb; i++ ) + mpIn->get(); +} + +//========================================================================= +// +// Methods of class cEmailReportViewer +// +//========================================================================= + +cEmailReportViewer::cEmailReportViewer( const cFCOReportHeader& h, const cFCOReport& r, + const TSTRING &address, bool bForceFullReport /*= false */) + : cTextReportViewer( h, r ), mbForceFullReport(bForceFullReport) +{ + mAddress = address; +} + +bool cEmailReportViewer::IgnoreThisSpec(const cFCOSpecAttr *attr) +{ + // IgnoreThisSpec - returns false if the email address is specified + // for the given spec attributes. + + if (mbForceFullReport) + return false; + + + // loop through all email addresses for this spec + cFCOSpecAttrEmailIter emailIter(*attr); + for(emailIter.SeekBegin(); ! emailIter.Done(); emailIter.Next()) + { + if (emailIter.EmailAddress() == mAddress) + return false; // Don't ignore it. It applies to me. + } + + return true; // Ignore it. It doesn't have my name on it. +} + +bool cEmailReportViewer::WantOutputObjectSummary() +{ + // This area is not useful unless you're doing the ballot box thing, + // which is not applicable to emailed reports. + return false; +} + +bool cEmailReportViewer::CanUpdate() +{ + // this derived class does not allow "DisplayReportAndHaveUserUpdateIt()" + return false; +} + + + + +//========================================================================= +// 6/16/99 -- new reporting stuff +//========================================================================= +TSTRING cTextReportViewer::SingleLineReport() +{ + TOSTRINGSTREAM sstrReport; + ASSERT( mpReport != 0 ); + ASSERT( mpHeader != 0 ); + + // + // get current time + // + tm* ptm = cTimeUtil::TimeToDateLocal( mpHeader->GetCreationTime() ); + if( NULL == ptm ) + ThrowAndAssert( ePoly() ); + + // + // format time: YYYYMMDDHHMMSS + // + TCHAR szDate[256]; + _tcsftime( szDate, countof( szDate ), _T("%Y%m%d%H%M%S"), ptm ); + + sstrReport << TSS_GetString( cTW, tw::STR_TRIPWIRE_REPORT_SHORT ); + sstrReport << _T(" "); + sstrReport << mpHeader->GetSystemName(); + sstrReport << _T(" "); + sstrReport << szDate; + + // + // get report stats + // + int nAddedTotal = 0; + int nRemovedTotal = 0; + int nChangedTotal = 0; + int nViolations = 0; + int maxSeverityViolated = 0; + + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + // We need to at least get the max severity in this function + cFCOReportSpecIter ri( genreIter ); + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + int nAdded = ri.GetAddedSet()->Size(); + int nRemoved = ri.GetRemovedSet()->Size(); + int nChanged = ri.GetNumChanged(); + + nAddedTotal += nAdded; + nRemovedTotal += nRemoved; + nChangedTotal += nChanged; + + if( nAdded || nRemoved || nChanged ) + { + // update the max severity + if( maxSeverityViolated < ri.GetAttr()->GetSeverity() ) + maxSeverityViolated = ri.GetAttr()->GetSeverity(); + + nViolations += ( nAdded + nRemoved + nChanged ); + } + } + } + + sstrReport << _T(" ") << TSS_GetString( cTW, tw::STR_VIOLATIONS_SHORT ) << _T(":") << nViolations; + sstrReport << _T(" ") << TSS_GetString( cTW, tw::STR_MAX_SEV_SHORT ) << _T(":") << maxSeverityViolated; + sstrReport << _T(" ") << TSS_GetString( cTW, tw::STR_ADDED_SHORT ) << _T(":") << nAddedTotal; + sstrReport << _T(" ") << TSS_GetString( cTW, tw::STR_REMOVED_SHORT ) << _T(":") << nRemovedTotal; + sstrReport << _T(" ") << TSS_GetString( cTW, tw::STR_CHANGED_SHORT ) << _T(":") << nChangedTotal; + + return sstrReport.str(); +} + + +void cTextReportViewer::OutputParseableReport() +{ + // iterate over all genres in a report + cFCOReportGenreIter genreIter( *mpReport ); + for( genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next() ) + { + SetUpForNewGenre( genreIter ); + + // iterate over all specs in a genre + cFCOReportSpecIter ri( genreIter ); + for( ri.SeekBegin(); !ri.Done(); ri.Next() ) + { + // iterate over all removed fcos + const cIterProxy pSetIterAdded = ri.GetAddedSet()->GetIter(); + for( pSetIterAdded->SeekBegin(); !pSetIterAdded->Done(); pSetIterAdded->Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_ADDED ) << _T(":\t"); + (*mpOut) << mpCurNT->ToStringDisplay( pSetIterAdded->FCO()->GetName(), true ) << endl; + } + + // iterate over all removed fcos + const cIterProxy pSetIterRemoved = ri.GetRemovedSet()->GetIter(); + for( pSetIterRemoved->SeekBegin(); !pSetIterRemoved->Done(); pSetIterRemoved->Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_REMOVED ) << _T(":\t"); + (*mpOut) << mpCurNT->ToStringDisplay( pSetIterRemoved->FCO()->GetName(), true ) << endl; + } + + // iterate over all changed fcos + cFCOReportChangeIter changedIter( ri ); + for( changedIter.SeekBegin(); !changedIter.Done(); changedIter.Next() ) + { + (*mpOut) << TSS_GetString( cTW, tw::STR_CHANGED ) << _T(":\t"); + (*mpOut) << mpCurNT->ToStringDisplay( changedIter.GetNew()->GetName(), true ) << endl; + } + } + } +} + +char cTextReportViewer::PeekChar() +{ + return char_traits:: + to_char_type( + mpIn->peek() ); +} + + +// TODO:BAM -- man is this function sloppy!!! +// The only reason that this function would fail would be that the text report +// was corrupted, like um, binarily corrupted. (that is, anything a text editor +// would put in here would be readable) +void cTextReportViewer::GetChar() +{ + cDebug d("cTextReportViewer::GetChar"); + ASSERT( sizeof( mCurrentChar ) >= MB_CUR_MAX ); // mCurrentChar holds a mb character for current locale + + // initialize mCurrentChar + mCurrentCharSize = 0; + for( int i = 0; i < (int)sizeof( mCurrentChar ); i++ ) + mCurrentChar[i] = 0; + + static const std::istream::char_type eof = + std::char_traits< char >::to_char_type( + std::char_traits< char >::eof() ); + + for( size_t nch = 0; nch < (size_t)MB_CUR_MAX; nch++ ) + { + if( mpIn->eof() || PeekIsEOF() ) + { + // should be first byte we read + if( nch != 0 ) + throw eTextReportViewerReportCorrupt(); + + if( PeekIsEOF() ) + { + // get the eof char so that mpIn->eof() will return true + mpIn->get(); + } + + d.TraceDebug( _T("Found EOF\n") ); + + mCurrentChar[0] = eof; + mCurrentCharSize = 1; + + return; + } + else + { + if( ! mpIn->good() ) + { + d.TraceDebug( _T("Input stream error.\n") ); + throw eTextReportViewerReportCorrupt(); + } + + // get character from input stream + std::istream::char_type ch = + std::char_traits::to_char_type( + mpIn->get() ); + + // add character to mb buffer + mCurrentChar[nch] = ch; + mCurrentCharSize++; + + // have we found a complete mb character yet? + if( 0 <= mbtowc( NULL, mCurrentChar, mCurrentCharSize ) ) + { + // completed a valid mb charactter + return; + } + else + { + // incomplete mb char -- keep reading in bytes + } + } + } + + // sequence was not a valid mb character + // (searched MB_CUR_MAX chars and didn't find a complete mb character) + d.TraceDebug( _T("Invalid mb char found!\n") ); +#ifdef _DEBUG + for( int j = 0; j < MB_CUR_MAX; j++ ) + d.TraceDebug( _T("%u\n"), (size_t)(unsigned char)mCurrentChar[j] ); +#endif + ASSERT( false ); + throw eTextReportViewerReportCorrupt(); +} + +void cTextReportViewer::AppendChar( std::string& str ) +{ + for( size_t s = 0; s < mCurrentCharSize; s++ ) + str += mCurrentChar[s]; +} + diff --git a/src/tw/textreportviewer.h b/src/tw/textreportviewer.h new file mode 100644 index 0000000..ffd73a7 --- /dev/null +++ b/src/tw/textreportviewer.h @@ -0,0 +1,301 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// textreportviewer.h -- definitions for textreportviewer class +// + +#ifndef __TEXTREPORTVIEWER_H +#define __TEXTREPORTVIEWER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif +#ifndef __ERROR_H +#include "core/error.h" +#endif +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class cFCOReport; +class cFCOReportSpecIter; +class cFCOName; +class cFCOReportHeader; +class cFCOReportGenreIter; +class iFCOPropDisplayer; +class cFCOPropVector; +class iFCO; +class cFCOSpecAttr; +class iFCONameTranslator; +class cErrorQueueIter; +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +TSS_EXCEPTION( eTextReportViewer, eError ); +TSS_EXCEPTION( eTextReportViewerFileOpen, eTextReportViewer ); +TSS_EXCEPTION( eTextReportViewerEditorLaunch, eTextReportViewer ); +TSS_EXCEPTION( eTextReportViewerReportCorrupt, eTextReportViewer ); + + +/////////////////////////////////////////////////////////////////////////////// +// cTextReportViewer +// +class cTextReportViewer +{ +public: + // + // ctors and dtors + // + cTextReportViewer( const cFCOReportHeader& h, cFCOReport& r ); + cTextReportViewer( const cFCOReportHeader& h, const cFCOReport& r ); + virtual ~cTextReportViewer(); + int Init( const cFCOReportHeader& h, cFCOReport& r ); + + enum ReportingLevel + { + SINGLE_LINE, + PARSEABLE, + SUMMARY_ONLY, + CONCISE_REPORT, + FULL_REPORT + }; + + // + // basic functionality + // + void DisplayReportAndHaveUserUpdateIt( const TSTRING& edName, ReportingLevel level = FULL_REPORT ); //throw (eFSServices, eTextReportViewer, eInternal); + // outputs the given report to a temp file, opens an editor, has + // the user view changes to the database, and, by selecting FCO entries, + // chooses which changes to write to the database. Unchecked entries + // are removed from the report + // edName is the name of the editor to use to update the report + + virtual void PrintTextReport( const TSTRING& strFilename, ReportingLevel level = FULL_REPORT ); //throw (eTextReportViewer); + // if strFilename is "-", will print to TCOUT + virtual void PrintTextReport( TOSTREAM& ostr, ReportingLevel level = FULL_REPORT ); //throw (eTextReportViewer); + // prints the report to the specified ostream + + TSTRING SingleLineReport(); + + int GetMaxSeverityViolated(); + int GetNumberViolations(); + +protected: + // + // don't let C++ create these functions + // + cTextReportViewer(); + cTextReportViewer( const cTextReportViewer& ); + cTextReportViewer& operator=( const cTextReportViewer& ); + + // + // private enums + // + enum + { + DETAILS_MARGIN = 4 + }; + + enum + { + TOKEN_GENRE, + TOKEN_BALLOT_BOX, + TOKEN_EOF + }; + + // + // private structures + // + struct RuleSummaryLine + { + TSTRING mSpecName; + int mSeverity; + int mAddedObjects; + int mRemovedObjects; + int mChangedObjects; + TSTRING mStartPoint; + + RuleSummaryLine() {} + RuleSummaryLine(const RuleSummaryLine& rhs) { *this = rhs; } + void operator = (const RuleSummaryLine& rhs) + { + mSpecName = rhs.mSpecName; + mSeverity = rhs.mSeverity; + mAddedObjects = rhs.mAddedObjects; + mRemovedObjects = rhs.mRemovedObjects; + mChangedObjects = rhs.mChangedObjects; + mStartPoint = rhs.mStartPoint; + } + }; + + // + // private typedefs + // + typedef std::set< cFCOName > FCOList; + typedef std::map< cGenre::Genre, FCOList* > GenreList; + typedef std::list< RuleSummaryLine > ObjectSummaryList; + + // + // private util functions + // + bool LaunchEditorOnFile( const TSTRING& strFilename, const TSTRING& edName ); //throw (eFSServices, eTextReportViewer); + void OutputTextReport(); //throw (eTextReportViewer); + + void PrintGenre( const cFCOReportGenreIter& genreIter ); //throw (eTextReportViewer); + void OutputGenreDelimiter( cGenre::Genre g, bool fDenoteBallotSection = false ); + void OutputSectionDelimiter( int nString ); + void OutputNumDetails( int nString, int nObjects ); + + void PrintBallotLine( const iFCO& FCO ); + void DisplayChangedProps( const iFCO* const pfcoOld, const iFCO* const pfcoNew, const cFCOPropVector* pv ); + void SetUpForNewGenre( const cFCOReportGenreIter& genreIter ); // call this after changing genres + + void OutputReportHeader(); + void OutputRulesSummary(); + void OutputRulesSummary( const cFCOReportGenreIter& genreIter ); + void CollateRulesSummary( const cFCOReportGenreIter& genreIter, ObjectSummaryList& summaryList ); + void OutputSpecHeader( const cFCOReportSpecIter &ri ); + void OutputFooter(); + + void PrintErrors(); + void ReportError( const cErrorQueueIter& eqIter ); + + void OutputObjectSummary (); + void OutputObjectSummary ( const cFCOReportGenreIter& genreIter ); + void OutputAddedSummary ( const cFCOReportSpecIter& ri, FCOList* pFCONameList ); + void OutputRemovedSummary( const cFCOReportSpecIter& ri, FCOList* pFCONameList ); + void OutputChangedSummary( const cFCOReportSpecIter& ri, FCOList* pFCONameList ); + + void OutputObjectDetails (); + void OutputObjectDetails ( const cFCOReportGenreIter& genreIter ); + void OutputAddedDetails ( const cFCOReportSpecIter& ri ); + void OutputRemovedDetails( const cFCOReportSpecIter& ri ); + void OutputChangedDetails( const cFCOReportSpecIter& ri ); + + bool IsChecked(); + TSTRING GetGenre(); + void InitOStream(); + void GetReportNumbers(); + + void ReadTextReport( const TSTRING& strFilename ); + + void GetChar(); + char PeekChar(); + bool PeekIsEOF(); + void AppendChar( std::string& str ); + + void EatSection(); + int FindNextLineToken(); + void GetGenreInfo( FCOList** ppCurList ); + void GetBallotInfo( FCOList* pCurList ); + void GetFCONameFromBallotLine( cFCOName& fcoName ); //throw (eTextReportViewer) + void RemoveFCOsFromReport();//throw (eTextReportViewer) + + void OutputParseableReport(); + + // + // overridables: + // + + virtual bool IgnoreThisSpec(const cFCOSpecAttr *attr); + virtual bool WantOutputReportHeader(); + virtual bool WantOutputRulesSummary(); + virtual bool WantOutputSpecHeader(); + virtual bool WantOutputObjectSummary(); + virtual bool WantOutputObjectDetails(); + // These function allows derived classes to tailor the report's apearance + + virtual bool CanUpdate(); + // override this to return false if DisplayReportAndHaveUserUpdateIt should not be allowed + + // + // data members + // + TOSTREAM* mpOut; + std::ifstream* mpIn; + bool mfUpdate; + const cFCOReportHeader* mpHeader; + const cFCOReport* mpReport; + int mMaxSeverityViolated; + int mNumberViolations; + int mErrorNum; + GenreList mFCOsRemoveFromReport; // collection of filenames to remove from report. + ReportingLevel mReportingLevel; + iFCOPropDisplayer* mpCurPD; + iFCONameTranslator* mpCurNT; + bool mfGotNumbers; + char mCurrentChar[6]; + size_t mCurrentCharSize; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// +// cEmailReportViewer +// +// this class is like cTextReportViewer, except that it only generates a report +// for the rules associated with the specified email address in the policy file. +// +class cEmailReportViewer : public cTextReportViewer +{ +public: + // constructor must be provided an email recipient's address + cEmailReportViewer( const cFCOReportHeader& h, const cFCOReport& r, + const TSTRING &address, + bool bForceFullReport = false); + + +protected: + // overrides + virtual bool IgnoreThisSpec(const cFCOSpecAttr *attr); + virtual bool WantOutputObjectSummary(); + virtual bool CanUpdate(); + + // data members + TSTRING mAddress; + bool mbForceFullReport; + +}; + + +#endif // __TEXTREPORTVIEWER_H + + diff --git a/src/tw/textreportviewer_t.cpp b/src/tw/textreportviewer_t.cpp new file mode 100644 index 0000000..d42440a --- /dev/null +++ b/src/tw/textreportviewer_t.cpp @@ -0,0 +1,461 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// textreportviewer_t.cpp -- tests textreportviewer +// + +#include "stdtw.h" +#include +#include + +#include "tw/fcoreport.h" +#include "fco/fcospecimpl.h" +#include "fco/fcosetimpl.h" +#include "fs/fsobject.h" +#include "core/serializerimpl.h" +#include "core/archive.h" +#include "test/test.h" +#include "core/errorbucketimpl.h" +#include "tw/textreportviewer.h" +#include "fs/fspropset.h" +#include "fs/fspropcalc.h" +#include "core/fsservices.h" +#include +#include +#include "fco/fcospechelper.h" +#include "fco/fcospecattr.h" +#include "tw/fcoreportutil.h" +#include "tw/headerinfo.h" + +#ifdef FIXED_TRV_TEST_SUITE + +void MakeFile( TSTRING& fcoNameMakeMe ); +void MakeDir( const TCHAR* const lpszDirName ); + +// we use this instead of TraceContents() so we can test the report iterators. +static void TraceReport(const cFCOReport& r, cDebug& d) +{ + d.TraceDebug("Global Error Queue:\n"); + r.GetErrorQueue()->TraceContents(); + + cFCOReportGenreIter genreIter(r); + int genreCount = 0; + + for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next()) + { + d.TraceDebug("> Genre [%d]:\n", genreCount); + + cFCOReportSpecIter specIter(genreIter); + int ct = 0; + + for(specIter.SeekBegin(); ! specIter.Done(); specIter.Next(), ct++) + { + d.TraceDebug(">>> Spec [%d]:\n", ct); + ASSERT(specIter.GetSpec()); + specIter.GetSpec()->TraceContents(); + specIter.GetErrorQueue()->TraceContents(); + + d.TraceDebug(">>> Added Files:\n"); + specIter.GetAddedSet()->TraceContents(); + d.TraceDebug(">>> Removed Files:\n"); + specIter.GetRemovedSet()->TraceContents (); + + // trace out changed files + cFCOReportChangeIter changeIter(specIter); + int changeCtr = 0; + for(changeIter.SeekBegin(); ! changeIter.Done(); changeIter.Next(), changeCtr++) + { + d.TraceDebug(">>>>> Changed fco [%d]\n", changeCtr); + d.TraceDebug(">>>>> Old FCO:\n"); + changeIter.GetOld()->TraceContents(); + d.TraceDebug(">>>>> New FCO:\n"); + changeIter.GetNew()->TraceContents(); + changeIter.GetChangeVector().TraceContents(); + } + } + } +} + +void TestTextReportViewer() +{ + cFCOReport report; + cFCOReportGenreIter genreIter(report); + cFCOReportSpecIter specIter(genreIter); + + cDebug d("TestFCOReport"); + + cFCOName fcoNameSpec1; + cFCOName fcoNameSpec2; + TSTRING fcoNameTempFile; + try + { + iFSServices* pFSServices = iFSServices::GetInstance(); + ASSERT( pFSServices ); + + TSTRING fcoNameTempDir; + pFSServices->GetTempDirName( fcoNameTempDir ); + + fcoNameSpec1 = fcoNameTempDir += _T("SPEC1/"); + fcoNameSpec2 = fcoNameTempDir += _T("SPEC2/"); + + pFSServices->Mkdir( fcoNameTempDir ); + pFSServices->Mkdir( fcoNameSpec1.AsString() ); + pFSServices->Mkdir( fcoNameSpec2.AsString() ); + + fcoNameTempFile = fcoNameTempDir += _T("twtempXXXXXX"); + pFSServices->MakeTempFilename( fcoNameTempFile ); + } + catch(eFSServices& /* e */) + { + // TODO: properly handle error + ASSERT( false ); + } + + // need two prop calcs because..... + // if cFSPropCalc::VisitFSObject succeeds, cFSPropCalc stores the FCO in + // an internal set (why, I don't know), and the cFCOSet ASSERTs that the same + // FCO isn't inserted more than once. But since we visit changed FCOs twice + // in this test routine, we need two calcs. Make sense? Oh, well. + cFSPropCalc* pPropCalc = new cFSPropCalc; + cFSPropCalc* pPropCalc2 = new cFSPropCalc; + + + cFCOSpecStopPointSet *pStopPts = new cFCOSpecStopPointSet; + cFCOSpecImpl* pSpec = new cFCOSpecImpl( fcoNameSpec1.AsString(), NULL, pStopPts); + cFCOSpecAttr* pAttr = new cFCOSpecAttr; + + + cFCOPropVector v; + for( int i = 0; i < 32; i++ ) + v.AddItem( i ); + + pPropCalc->SetPropVector(v); + pPropCalc2->SetPropVector(v); + + + TSTRING fcoNameMakeMe; + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/added_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* addedFCO = new cFSObject( cFCOName(fcoNameMakeMe)); + pPropCalc->VisitFSObject( *addedFCO ); + + + // MakeTempFile can't handle strings with escaped quotes, so we'll have to do this ourselves + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/\"quoted\\_and_backslashed_file1\""); + //TOFSTREAM file1( fcoNameMakeMe.c_str() ); + //ASSERT( file1 ); + //file1.close(); + + cFSObject* addedFCO2 = new cFSObject( cFCOName(fcoNameMakeMe) ); + //pPropCalc->VisitFSObject( *addedFCO2 ); + + + // MakeTempFile can't handle strings with escaped quotes, so we'll have to do this ourselves + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/quoted_file\"2\"XXXXXX"); + //TOFSTREAM file2( fcoNameMakeMe.c_str() ); + //ASSERT( file2 ); + //file2.close(); + + cFSObject* addedFCO3 = new cFSObject( cFCOName(fcoNameMakeMe) ); + //pPropCalc->VisitFSObject( *addedFCO3 ); + + + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/removed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* removedFCO = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *removedFCO ); + + + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/removed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* removedFCO2 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *removedFCO2 ); + + pSpec->SetStartPoint( fcoNameSpec1 ); + pAttr->SetName( fcoNameSpec1.AsString() ); + pAttr->SetSeverity(53); + pStopPts->Add( cFCOName( fcoNameSpec1.AsString() + _T("/End1")) ); + report.AddSpec(0x00020001, pSpec, pAttr, &specIter); // TODO:bam - use cFS::Genre + pAttr->Release(); + + + specIter.GetAddedSet()->Insert(addedFCO); + specIter.GetAddedSet()->Insert(addedFCO2); + specIter.GetAddedSet()->Insert(addedFCO3); + specIter.GetRemovedSet()->Insert(removedFCO); + specIter.GetRemovedSet()->Insert(removedFCO2); + + // make changed FCO1 + cFCOPropVector changedPropVector1; + + + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/changed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* oldChangedFCO = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *oldChangedFCO ); + (static_cast (oldChangedFCO->GetPropSet()))->SetSize(123); + //(static_cast (oldChangedFCO->GetPropSet()))->SetUID(_T("old")); + + cFSObject* newChangedFCO = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc2->VisitFSObject( *newChangedFCO ); + (static_cast (newChangedFCO->GetPropSet()))->SetSize(666); + //(static_cast (newChangedFCO->GetPropSet()))->SetUID(_T("new")); + + changedPropVector1.AddItem(cFSPropSet::PROP_SIZE); + changedPropVector1.AddItem(cFSPropSet::PROP_UID); + report.AddChangedFCO(specIter, oldChangedFCO, newChangedFCO, changedPropVector1); + + // make changed FCO2 + cFCOPropVector changedPropVector2; + + fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/changed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* oldChangedFCO2 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *oldChangedFCO2 ); + + //(static_cast (oldChangedFCO2->GetPropSet()))->SetGSID( _T("S-1-1-0") ); + + cFSObject* newChangedFCO2 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc2->VisitFSObject( *newChangedFCO2 ); + //(static_cast (newChangedFCO2->GetPropSet()))->SetGSID( _T("S-1-1-1") ); + + //changedPropVector2.AddItem(cFSPropSet::PROP_GSID); + report.AddChangedFCO(specIter, oldChangedFCO2, newChangedFCO2, changedPropVector2); + + // add some errors +// report.GetErrorQueue()->AddError(eError(_T("this is a general error"))); + // report.GetErrorQueue()->AddError(eError(_T("this too is a general error"))); + + + cFCOSpecStopPointSet *pStopPts2 = new cFCOSpecStopPointSet; + cFCOSpecImpl* pSpec2 = new cFCOSpecImpl( fcoNameSpec2.AsString(), NULL, pStopPts2); + cFCOSpecAttr* pAttr2 = new cFCOSpecAttr; + + fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/added_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* addedFCO5 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *addedFCO5 ); + + fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/removed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* removedFCO5 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *removedFCO5 ); + + pSpec2->SetStartPoint( fcoNameSpec2 ); + pAttr2->SetName( fcoNameSpec2.AsString() ); + pAttr2->SetSeverity(64); + pStopPts2->Add( cFCOName( fcoNameSpec2.AsString() + _T("/End2") ) ); + report.AddSpec(0x00020001, pSpec2, pAttr2, &specIter); // TODO:bam -- use cFS::Genre + pAttr2->Release(); + + specIter.GetAddedSet()->Insert(addedFCO5); + specIter.GetRemovedSet()->Insert(removedFCO5); + + + + // make changed FCO3 + cFCOPropVector changedPropVector3; + + fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/changed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* oldChangedFCO3 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *oldChangedFCO3 ); + (static_cast (oldChangedFCO3->GetPropSet()))->SetBlockSize(313222); + + cFSObject* newChangedFCO3 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc2->VisitFSObject( *newChangedFCO3 ); + (static_cast (newChangedFCO3->GetPropSet()))->SetBlockSize(22213145); + + changedPropVector3.AddItem(cFSPropSet::PROP_BLOCK_SIZE); + report.AddChangedFCO(specIter, oldChangedFCO3, newChangedFCO3, changedPropVector3); + + // make changed FCO4 + cFCOPropVector changedPropVector4; + + fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/changed_fileXXXXXX"); + MakeFile( fcoNameMakeMe ); + cFSObject* oldChangedFCO4 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc->VisitFSObject( *oldChangedFCO4 ); + (static_cast (oldChangedFCO4->GetPropSet()))->SetSize(9104498); + (static_cast (oldChangedFCO4->GetPropSet()))->SetMode( S_IREAD | S_IWRITE ); + + cFSObject* newChangedFCO4 = new cFSObject( cFCOName(fcoNameMakeMe) ); + pPropCalc2->VisitFSObject( *newChangedFCO4 ); + (static_cast (newChangedFCO4->GetPropSet()))->SetSize(66); + (static_cast (newChangedFCO4->GetPropSet()))->SetMode( S_IREAD | S_IWRITE | S_IEXEC ); + + changedPropVector4.AddItem(cFSPropSet::PROP_SIZE); + changedPropVector4.AddItem(cFSPropSet::PROP_MODE); + report.AddChangedFCO(specIter, oldChangedFCO4, newChangedFCO4, changedPropVector4); + + specIter.SeekBegin(); + specIter.Next(); + //specIter.GetErrorQueue()->AddError(2, "this is an \"/etc2\" spec error",NULL); + + + d.TraceDebug(_T("\n======================================================\nStart PrintTextReport...\n======================================================\n\n\n")); + + TSTRING tstrEmpty( _T("") ); + cFCOReportHeader rhi; + cFCOReportUtil::FinalizeReport( report ); + cTextReportViewer trv; + trv.DisplayReportAndHaveUserUpdateIt( rhi, report, _T("") ); + + // test writing of USID + cFileArchive outFile; + outFile.OpenReadWrite(_T("tmp.twr")); + cSerializerImpl outSer(outFile, cSerializerImpl::S_WRITE); + + //TraceReport(report, d); + outSer.Init(); + outSer.WriteObject(&report); + outSer.Finit(); + + outFile.Close(); + + cFileArchive inFile; + inFile.OpenRead(_T("tmp.twr")); + cSerializerImpl inSer(inFile, cSerializerImpl::S_READ); + + cFCOReport inReport; + + inSer.Init(); + inSer.ReadObject(&inReport); + inSer.Finit(); + + d.TraceDebug("Read in serialized report:\n"); + //TraceReport(inReport, d); + trv.PrintTextReport( rhi, inReport, TSTRING( TEMP_DIR _T( "/test2.txt" ) ) ); + + //TODO: this does not work any more + //trv.LaunchEditorOnFile( TSTRING( TEMP_DIR _T("/test2.txt") ), _T("") ); + + + // look at results + trv.PrintTextReport( rhi, report, fcoNameTempFile ); + //TODO: this does not work any more + //cTextReportViewer::LaunchEditorOnFile( fcoNameTempFile, _T("") ); + + + iFSServices* pFSServices = iFSServices::GetInstance(); + ASSERT( pFSServices ); + pFSServices->FileDelete( addedFCO->GetName().AsString() ); + pFSServices->FileDelete( addedFCO2->GetName().AsString() ); + pFSServices->FileDelete( addedFCO3->GetName().AsString() ); + pFSServices->FileDelete( addedFCO5->GetName().AsString() ); + pFSServices->FileDelete( removedFCO->GetName().AsString() ); + pFSServices->FileDelete( removedFCO2->GetName().AsString() ); + pFSServices->FileDelete( removedFCO5->GetName().AsString() ); + pFSServices->FileDelete( newChangedFCO->GetName().AsString() ); + pFSServices->FileDelete( newChangedFCO2->GetName().AsString() ); + pFSServices->FileDelete( newChangedFCO3->GetName().AsString() ); + pFSServices->FileDelete( newChangedFCO4->GetName().AsString() ); + pFSServices->FileDelete( fcoNameTempFile ); + + // don't remove TEMP_DIR since other people may be using it + pFSServices->Rmdir( fcoNameSpec1.AsString() ); + pFSServices->Rmdir( fcoNameSpec2.AsString() ); + + pSpec->Release(); + pSpec2->Release(); + addedFCO->Release(); + addedFCO2->Release(); + addedFCO3->Release(); + addedFCO5->Release(); + removedFCO->Release(); + removedFCO2->Release(); + removedFCO5->Release(); + delete pPropCalc; + delete pPropCalc2; + oldChangedFCO->Release(); + newChangedFCO->Release(); + oldChangedFCO2->Release(); + newChangedFCO2->Release(); + oldChangedFCO3->Release(); + newChangedFCO3->Release(); + oldChangedFCO4->Release(); + newChangedFCO4->Release(); + + return; +} + +void MakeFile( TSTRING& strNameMakeMe ) +{ + try + { + iFSServices* pFSServices = iFSServices::GetInstance(); ASSERT( pFSServices ); + pFSServices->MakeTempFilename( strNameMakeMe ); + + std::string strA; + for( TSTRING::iterator i = strNameMakeMe.begin(); i != strNameMakeMe.end(); i++ ) + { + char ach[4]; + ASSERT( MB_CUR_MAX <= 4 ); + + int n = wctomb( ach, *i ); + ASSERT( n != -1 ); + + for( int j = 0; j < n; j++ ) + strA += ach[j]; + } + + TOFSTREAM file( strA.c_str() ); + ASSERT( file ); + file.close(); + } + catch( eFSServices e ) + { + ASSERT( false ); + } + catch( ... ) + { + ASSERT( false ); + } +} + +void MakeDir( const TCHAR* const lpszDirName ) +{ + try + { + iFSServices* pFSServices = iFSServices::GetInstance(); + TSTRING newdir(lpszDirName); + + pFSServices->Mkdir( newdir ); + } + catch( eFSServices e ) + { + ASSERT( false ); + } +} + +#endif //FIXED_TRV_TEST_SUITE + diff --git a/src/tw/tw.cpp b/src/tw/tw.cpp new file mode 100644 index 0000000..6e09067 --- /dev/null +++ b/src/tw/tw.cpp @@ -0,0 +1,70 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: tw.cpp +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtw.h" +#include "tw.h" +#include "twerrors.h" + +#include "core/core.h" +#include "db/db.h" +#include "twcrypto/twcrypto.h" +#include "fco/fco.h" +#include "util/util.h" +// +// NOTE:mdb -- these are _only_ needed for cTWInit!!! A sign of something?? +// +#include "fs/fs.h" + +/////////////////////////////////////////////////////////////////////////////// +// cTW +/////////////////////////////////////////////////////////////////////////////// +TSS_ImplementPackage( cTW ) + +cTW::cTW() +{ + TSS_Dependency( cCore ); + TSS_Dependency( cDb ); + TSS_Dependency( cTWCrypto ); + TSS_Dependency( cFCO ); + TSS_Dependency( cUtil ); + TSS_Dependency( cFS ); + + TSS_REGISTER_PKG_ERRORS( tw ) +} + +// eof: tw.cpp + diff --git a/src/tw/tw.h b/src/tw/tw.h new file mode 100644 index 0000000..547bfe7 --- /dev/null +++ b/src/tw/tw.h @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: tw.h +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// Package initialization class +// + +#ifndef __TW_H +#define __TW_H + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include "core/package.h" + +TSS_BeginPackage( cTW ) + + TSS_DECLARE_STRINGTABLE; + +public: + cTW(); + +TSS_EndPackage( cTW ) + + +#endif//__TW_H + diff --git a/src/tw/twerrors.cpp b/src/tw/twerrors.cpp new file mode 100644 index 0000000..24a50d9 --- /dev/null +++ b/src/tw/twerrors.cpp @@ -0,0 +1,118 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// twerrors.cpp +// +// Registers all error strings in the tw package +// +#include "stdtw.h" +#include "core/errortable.h" + +#include "twerrors.h" +#include "configfile.h" +#include "twutil.h" +#include "textreportviewer.h" +#include "filemanipulator.h" +#include "fcodatabasefile.h" + +TSS_BEGIN_ERROR_REGISTRATION( tw ) + +// +// General +// +TSS_REGISTER_ERROR( eTWDbNotEncrypted(), _T("Database is not encrypted.") ); +TSS_REGISTER_ERROR( eTWDbDoesntHaveGenre(), _T("Section not found in database.") ); +TSS_REGISTER_ERROR( eTWDbHasNoGenres(), _T("Database file contains no sections!") ); +TSS_REGISTER_ERROR( eTWBadPropsToIgnore(), _T("Invalid property mask specified on command line:") ); +TSS_REGISTER_ERROR( eTWUnknownSectionName(), _T("Unknown section name specified on command line:") ); +TSS_REGISTER_ERROR( eTWBadSeverityName(), _T("Unknown severity name (valid values are [low, medium, high]).") ); +TSS_REGISTER_ERROR( eTWCfgUnencrypted(), _T("Config file is unencrypted.") ); +TSS_REGISTER_ERROR( eTWPolUnencrypted(), _T("Policy file is unencrypted.") ); +TSS_REGISTER_ERROR( eTWSyslog(), _T("Syslog reporting failure.") ); + + +// +// Config File +// +TSS_REGISTER_ERROR( eConfigFile(), _T("Configuration file error.") ) +TSS_REGISTER_ERROR( eConfigFileNoEq(), _T("Configuration file contains a line with no \"=\".") ) +TSS_REGISTER_ERROR( eConfigFileNoKey(), _T("Configuration file contains a line with no variable.") ) +TSS_REGISTER_ERROR( eConfigFileAssignToPredefVar(), _T("Configuration file assigns a value to a read only variable.") ) +TSS_REGISTER_ERROR( eConfigFileUseUndefVar(), _T("Configuration file uses an undefined variable.") ) +TSS_REGISTER_ERROR( eConfigFileMissReqKey(), _T("Configuration file does not define mandatory variable(s).") ) +TSS_REGISTER_ERROR( eConfigFileEmptyVariable(), _T("Configuration file assigns an empty value to a variable.") ) +TSS_REGISTER_ERROR( eConfigFileMissingRightParen(), _T("Configuration file variable has no right parenthesis.") ) + + +// +// TW Util +// +TSS_REGISTER_ERROR( eTWUtil(), _T("Tripwire error.") ) +TSS_REGISTER_ERROR( eTWUtilNotFullPath(), _T("Object name is not fully qualified; skipping.") ) +TSS_REGISTER_ERROR( eTWUtilCfgKeyMismatch(), _T("Config file site key mismatch.") ) +TSS_REGISTER_ERROR( eTWUtilCorruptedFile(), _T("File is corrupted.") ) +TSS_REGISTER_ERROR( eTWUtilBadPassLocal(), _T("Incorrect local passphrase.") ) +TSS_REGISTER_ERROR( eTWUtilBadPassSite(), _T("Incorrect site passphrase.") ) +TSS_REGISTER_ERROR( eTWUtilEchoModeSet(), _T("Could not set console to no echo mode.") ) +TSS_REGISTER_ERROR( eTWUtilPolUnencrypted(), _T("Policy file is unencrypted.") ) +TSS_REGISTER_ERROR( eTWUtilObjNotInDb(), _T("Object not found in the database.") ) + + +// +// Text Report Viewer +// +TSS_REGISTER_ERROR( eTextReportViewer(), _T("Text report viewer error.") ) +TSS_REGISTER_ERROR( eTextReportViewerFileOpen(), _T("File could not be opened.") ) +TSS_REGISTER_ERROR( eTextReportViewerEditorLaunch(), _T("Editor could not be launched.") ) +TSS_REGISTER_ERROR( eTextReportViewerReportCorrupt(), _T("Report file could not be parsed. Report may be corrupt.") ) + +// +// File Manipulator +// +TSS_REGISTER_ERROR( eFileManip(), _T("File manipulation error.") ) +TSS_REGISTER_ERROR( eFileManipInvalidFile(), _T("Could not manipulate invalid file.") ) +TSS_REGISTER_ERROR( eFileManipFileRead(), _T("File could not be read.") ) +TSS_REGISTER_ERROR( eFileManipHeaderNotFound(), _T("File is not a Tripwire data file.") ) +TSS_REGISTER_ERROR( eFileManipFileNotFound(), _T("File could not be found.") ) +TSS_REGISTER_ERROR( eFileManipNotEncrypted(), _T("File is not encrypted.") ) +TSS_REGISTER_ERROR( eFileManipMissingKey(), _T("Key not supplied.") ) +TSS_REGISTER_ERROR( eFileManipNotWritable(), _T("File is not writable.") ) +TSS_REGISTER_ERROR( eFileManipUnrecognizedFileType(), _T("Unrecognized file type.") ) + // TODO:mdb -- why was this commented out of twstrings and the error table? + +// +// Database File +// +TSS_REGISTER_ERROR( eFCODbFile(), _T("Database file error.") ); +TSS_REGISTER_ERROR( eFCODbFileTooBig(), _T("Database file too large.") ); + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/tw/twerrors.h b/src/tw/twerrors.h new file mode 100644 index 0000000..df2613c --- /dev/null +++ b/src/tw/twerrors.h @@ -0,0 +1,63 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twerror.h -- +// + +#ifndef __TWERROR_H +#define __TWERROR_H + +//////////////////////////////////////// +// TODO:mdb !!!! These do _not_ belong here!!! Did I do this???? +// +#include "core/error.h" +TSS_EXCEPTION( eTW, eError ); +TSS_EXCEPTION( eTWDbNotEncrypted, eTW ); +TSS_EXCEPTION( eTWDbDoesntHaveGenre, eTW ); +TSS_EXCEPTION( eTWDbHasNoGenres, eTW ); +TSS_EXCEPTION( eTWBadPropsToIgnore, eTW ); +TSS_EXCEPTION( eTWUnknownSectionName, eTW ); +TSS_EXCEPTION( eTWBadSeverityName, eTW ); +TSS_EXCEPTION( eTWCfgUnencrypted, eTW ); +TSS_EXCEPTION( eTWPolUnencrypted, eTW ); +TSS_EXCEPTION( eTWSyslog, eTW ); + +// +// end (stuff that should move +/////////////////////////////////////// + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( tw ) + +#endif //#ifndef __TWERROR_H + diff --git a/src/tw/twinit.cpp b/src/tw/twinit.cpp new file mode 100644 index 0000000..5e1af78 --- /dev/null +++ b/src/tw/twinit.cpp @@ -0,0 +1,308 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twinit.cpp +// +// cTWInit -- initializes global objects for tw executables +// + +#include "stdtw.h" + +#include "twinit.h" +#include "fco/genreswitcher.h" +#include "core/fsservices.h" +#include "core/usernotifystdout.h" +#include "core/errorbucketimpl.h" +#include "core/timeconvert.h" +#include "fco/fconame.h" +#include "tw/systeminfo.h" +#include "core/twlocale.h" +#include "core/codeconvert.h" + +////////////////// +// the headers for objects we will need to register in RegisterAllSerializable() below. +#include "core/serializerimpl.h" +#include "fs/fsobject.h" +#include "fco/fcospecimpl.h" +#include "fco/fconame.h" +#include "tw/fcoreport.h" +#include "fco/fcosetimpl.h" +#include "fco/fcospechelper.h" +#include "fco/fcospecattr.h" +#include "fs/fspropdisplayer.h" +#include "tw/fcodatabasefile.h" +#include "core/fileheader.h" +#include "core/serstring.h" +#include "tw/headerinfo.h" +#include "fs/fspropset.h" +///////////////// + +// Used for package initialization +// +#include "core/package.h" +#include "tw/tw.h" + +#include "fco/fconame.h" + +#include "fs/fs.h" // object initialization +#if IS_UNIX +#include "core/unixfsservices.h" +#include "core/tw_signal.h" // to ignore SIGPIPE +#endif + + +//============================================================================= +// cTWInit_i +//============================================================================= +class cTWInit_i +{ +public: + cTWInit_i(); + ~cTWInit_i(); + // both shouldn't throw exceptions + + iFSServices* pFSServices; + cUserNotifyStdout unStdout; + cErrorTracer et; + cErrorReporter er; +}; + +cTWInit_i::cTWInit_i() + : pFSServices( NULL ) +{ + // package initialization + // + + TSS_Dependency( cFS ); +} + +cTWInit_i::~cTWInit_i() +{ + delete pFSServices; +} + +/////////////////////////////////////////////////////////////////////////////// +// RegisterAllSerializable() -- Register all serializable objects +/////////////////////////////////////////////////////////////////////////////// +static void RegisterAllSerializable() +{ + // Reference count objects + cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFSObject), cFSObject::Create); + cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFCOSpecImpl), cFCOSpecImpl::Create); + cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFCOSpecAttr), cFCOSpecAttr::Create); + + // Non-reference count objects + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCODatabaseFile), cFCODatabaseFile::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cErrorQueue), cErrorQueue::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOName), cFCOName::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOReport), cFCOReport::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSetImpl), cFCOSetImpl::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSpecStopPointSet), cFCOSpecStopPointSet::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSpecNoChildren), cFCOSpecNoChildren::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cSerializableNString), cSerializableNString::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cSerializableWString), cSerializableWString::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cHeaderInfo), cHeaderInfo::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCODbHeader), cFCODbHeader::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOReportHeader), cFCOReportHeader::Create); + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFSPropSet), cFSPropSet::Create); + + // prop displayers + cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFSPropDisplayer), cFSPropDisplayer::Create); + +} + +/////////////////////////////////////////////////////////////////////////////// +// SetExeDir +/////////////////////////////////////////////////////////////////////////////// +static bool SetExeDir( const TSTRING& strArgv0 ) +{ + ASSERT( ! strArgv0.empty() ); + + // record executable directory + TSTRING strFullPath; + if( iFSServices::GetInstance()->GetExecutableFilename( strFullPath, strArgv0 ) && !strFullPath.empty() ) + { + cSystemInfo::SetExePath(strFullPath); + + TSTRING::size_type s = strFullPath.find_last_of( _T('/') ); + // paths will always come back from GetExecutableFilename delimited with a forward slash + ASSERT( TSTRING::npos != s ); + if( TSTRING::npos != s ) + strFullPath.resize( s ); + cSystemInfo::SetExeDir(strFullPath); + } + else // error + { + ASSERT( false ); + cSystemInfo::SetExeDir(_T("")); + return false; + } + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ctor +/////////////////////////////////////////////////////////////////////////////// +cTWInit::cTWInit() +{ + mpData = new cTWInit_i(); +} + +/////////////////////////////////////////////////////////////////////////////// +// dtor +/////////////////////////////////////////////////////////////////////////////// +cTWInit::~cTWInit() +{ + delete mpData; + + // + // clear out the fco name tbl + // this helps the mem leak quest... + // + cFCOName::ClearNameTable(); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +void cTWInit::Init( const TSTRING& strArgv0 ) +{ + // package initialization... + // + TSS_Dependency( cTW ); // initialize all packages on program startup (exes + // should call this function (cTWInit::Init) on startup + + // we require 8-bit bytes for some functionality + ASSERT( sizeof( byte ) == sizeof( uint8 ) ); + + // + // set debug level + // NOTE:BAM -- this is also being set in cCore::cCore() because + // things in that constructor need to have a debug output as well. + // so this code here is redundant. + // + cDebug::SetDebugLevel( cDebug::D_DEBUG ); + cDebug::AddOutTarget( cDebug::OUT_STDOUT ); + + // ------------------------------------------------------------ + // BEG:RAD -- Does not belong here, moved to cCore::cCore! + // ------------------------------------------------------------ + // + // initialize locale + // + // cTWLocale::InitGlobalLocale(); + // ------------------------------------------------------------ + // END:RAD + // ------------------------------------------------------------ + + // ------------------------------------------------------------ + // BEG:RAD -- Does not belong here, moved to cCore::cCore! + // ------------------------------------------------------------ + // initialize code converter ( inits itself on creation, + // but initializing it here lets us see any errors immediately ) + // + // iCodeConverter::GetInstance(); + // ------------------------------------------------------------ + // END:RAD + // ------------------------------------------------------------ + + // + // set up the file system services + // +#if IS_UNIX + mpData->pFSServices = new cUnixFSServices; +#endif + ASSERT( mpData->pFSServices != 0 ); + iFSServices::SetInstance( mpData->pFSServices ); + + // + // save directory in which this executable resides + // + SetExeDir( strArgv0 ); + + // + // save current time + // + cSystemInfo::SetExeStartTime( cTimeUtil::GetTime() ); + + // assure that a default genre has been set and... + ASSERT( cGenre::GENRE_INVALID != cGenreSwitcher::GetInstance()->GetDefaultGenre() ); + // ...switch to it + cGenreSwitcher::GetInstance()->SelectGenre( cGenreSwitcher::GetInstance()->GetDefaultGenre() ); + + // initialize iUserNotify + iUserNotify::SetInstance( &mpData->unStdout ); + iUserNotify::GetInstance()->SetVerboseLevel(iUserNotify::V_NORMAL); + + // register serializable objects + RegisterAllSerializable(); + + // set up an error bucket that will spit things to stderr + mpData->et.SetChild( &mpData->er ); + errorQueue.SetChild( &mpData->et ); + +#if IS_UNIX + // ignore SIGPIPE + tw_sigign(SIGPIPE); //TODO: somebody add comment here! + + // We'll install handlers for each signal that would cause a core dump. + // the disposition will still be to exit, just without producing a core file. + // I'll emit an error statement that indicates the interrupt before the exit + // call. + tw_HandleSignal( SIGBUS ); // Handle Bus error signals without dumping core... + tw_HandleSignal( SIGSEGV ); // Segmentation fault + tw_HandleSignal( SIGQUIT ); // Quit signal - issued from terminal (CTRL-\) + tw_HandleSignal( SIGILL ); // Illegal instruction - probably won't be an issue. +#ifndef _DEBUG + tw_HandleSignal( SIGTRAP ); // We don't want to mess up the debugger in debug builds... +#endif + tw_HandleSignal( SIGABRT ); // Supposedly we can only get this signal by calling abort() + // ourselves, but to be on the safe side... +#ifdef SIGEMT + tw_HandleSignal( SIGEMT ); // Emulator trap. +#endif +#ifdef SIGSYS + tw_HandleSignal( SIGSYS ); // Bad system call. +#endif + tw_HandleSignal( SIGFPE ); // Floating point exception. + tw_HandleSignal( SIGXCPU ); // CPU time exceeded. Might very well be an issue for us. + tw_HandleSignal( SIGXFSZ ); // File size limit exceeded. + +#endif + + +} + + diff --git a/src/tw/twinit.h b/src/tw/twinit.h new file mode 100644 index 0000000..dd6c66d --- /dev/null +++ b/src/tw/twinit.h @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twutil.h +// +// cTWInit -- initializes global objects for tw executables +// + +#ifndef __ERRORBUCKETIMPL_H +#include "core/errorbucketimpl.h" +#endif + +class cTWInit_i; +class cTWInit +{ +public: + cTWInit(); // throw() // used to record exe dir + // will not throw exceptions + ~cTWInit(); // throw() + // will not throw exceptions + + void Init( const TSTRING& strArgv0 ); + // may throw exceptions + + cErrorQueue errorQueue; +private: + + cTWInit_i* mpData; +}; + diff --git a/src/tw/twstrings.cpp b/src/tw/twstrings.cpp new file mode 100644 index 0000000..0688e78 --- /dev/null +++ b/src/tw/twstrings.cpp @@ -0,0 +1,262 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twstrings.cpp +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#include "stdtw.h" +#include "twstrings.h" +#include "buildnum.h" + +#ifdef _UNICODE +# ifdef _DEBUG // lets leave out the "u" for non-debug +# define UNICODE_STR _T("u") +# else +# define UNICODE_STR _T("") +# endif +#else +# define UNICODE_STR _T("") +#endif + +#ifdef _DEBUG +# define DEBUG_STR _T("d") +#else +# define DEBUG_STR _T("") +#endif + +#define TSS_PRODUCT_NAME _T("Open Soure Tripwire(R) 2.4.2.2.") + +#define TSS_COPYRIGHT_NOTICE \ +_T("Open Source Tripwire 2.4 Portions copyright 2000 Tripwire, Inc. Tripwire is a registered\n\ +trademark of Tripwire, Inc. This software comes with ABSOLUTELY NO WARRANTY;\n\ +for details use --version. This is free software which may be redistributed\n\ +or modified only under certain conditions; see COPYING for details.\n\ +All rights reserved.") + + +#define TSS_COPYRIGHT_NOTICE_LONG \ +_T("The developer of the original code and/or files is Tripwire, Inc. Portions \n\ +created by Tripwire, Inc. are copyright 2000 Tripwire, Inc. Tripwire is a \n\ +registered trademark of Tripwire, Inc. All rights reserved.\n\ +\n\ +This program is free software. The contents of this file are subject to the \n\ +terms of the GNU General Public License as published by the Free Software \n\ +Foundation; either version 2 of the License, or (at your option) any later \n\ +version. You may redistribute it and/or modify it only in compliance with \n\ +the GNU General Public License.\n\ +\n\ +This program is distributed in the hope that it will be useful. However, \n\ +this program is distributed \"AS-IS\" WITHOUT ANY WARRANTY; INCLUDING THE \n\ +IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. \n\ +Please see the GNU General Public License for more details.\n\ +\n\ +You should have received a copy of the GNU General Public License along with \n\ +this program; if not, write to the Free Software Foundation, Inc., \n\ +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\ +\n\ +Nothing in the GNU General Public License or any other license to use the \n\ +code or files shall permit you to use Tripwire's trademarks, service marks, \n\ +or other intellectual property without Tripwire's prior written consent. \n\ +\n\ +If you have any questions, please contact Tripwire, Inc. at either \n\ +info@tripwire.org or www.tripwire.org.") + + +TSS_BeginStringtable( cTW ) + + TSS_StringEntry( tw::STR_ERR_MISSING_LOCAL_KEY, _T("No local key specified.")), + TSS_StringEntry( tw::STR_ERR_MISSING_SITE_KEY, _T("No site key specified.")), + TSS_StringEntry( tw::STR_ERR_MISSING_POLICY, _T("No policy file specified.")), + TSS_StringEntry( tw::STR_ERR_MISSING_DB, _T("No database file specified.")), + TSS_StringEntry( tw::STR_ERR_MISSING_REPORT, _T("No report file specified.")), + TSS_StringEntry( tw::STR_ERR_MISSING_EDITOR, _T("No text editor specified in configuration file,\n") + _T("command line, or in VISUAL or EDITOR environment variables.")), + + TSS_StringEntry( tw::STR_ERR_WRONG_PASSPHRASE_SITE, _T("Incorrect site passphrase.") ), + TSS_StringEntry( tw::STR_ERR_WRONG_PASSPHRASE_LOCAL, _T("Incorrect local passphrase.") ), + +#if defined(CONFIG_DIR) + // NOTE:mdb if we are following the FHS, then the config file lives in /etc/tripwire and not in + // the current working directory + TSS_StringEntry( tw::STR_DEF_CFG_FILENAME, _T(CONFIG_DIR"/tw.cfg")), +#else + TSS_StringEntry( tw::STR_DEF_CFG_FILENAME, _T("/etc/tw.cfg")), +#endif + + TSS_StringEntry( tw::STR_WIN_NT_ONLY, _T("Open Source Tripwire(R) runs only on Windows NT.")), + TSS_StringEntry( tw::STR_GET_HELP, _T("Use --help to get help.")), + TSS_StringEntry( tw::STR_NEWLINE, _T("\n")), + TSS_StringEntry( tw::STR_ERR_TWCFG_CANT_READ, _T("Configuration file could not be read.")), + TSS_StringEntry( tw::STR_ERR_NO_MODE, _T("No mode specified.")), + TSS_StringEntry( tw::STR_UNKOWN_MODE_SPECIFIED, _T("Unknown mode specified: ")), + TSS_StringEntry( tw::STR_ERR2_BAD_MODE_SWITCH, _T("Unrecognized mode: ")), + + TSS_StringEntry( tw::STR_OPEN_POLICY_FILE, _T("Opening policy file: ")), + TSS_StringEntry( tw::STR_PARSING_POLICY, _T("Parsing policy file: ")), + TSS_StringEntry( tw::STR_ERR_REPORT_READ, _T("Report file could not be read.")), + TSS_StringEntry( tw::STR_REPORT_NOT_ENCRYPTED, _T("Note: Report is not encrypted.\n")), + TSS_StringEntry( tw::STR_ERR_DB_READ, _T("Database file could not be read.")), + + TSS_StringEntry( tw::STR_CUR_LINE, _T("Line number ") ), + + TSS_StringEntry( tw::STR_ENTER_LOCAL_PASSPHRASE, _T("Please enter your local passphrase: ") ), + TSS_StringEntry( tw::STR_ENTER_SITE_PASSPHRASE, _T("Please enter your site passphrase: ") ), + TSS_StringEntry( tw::STR_ENTER_PROVIDED_PASSPHRASE, _T("Please enter passphrase: ") ), + + TSS_StringEntry( tw::STR_DB_NOT_UPDATED, _T("The database was not updated. ") ), + TSS_StringEntry( tw::STR_IGNORE_PROPS, _T("Ignoring properties: ") ), + TSS_StringEntry( tw::STR_NOT_IMPLEMENTED, _T("Feature not implemented yet: ") ), + TSS_StringEntry( tw::STR_REPORT_EMPTY, _T("The report contains no new data, the database will not be updated.\n") ), + + TSS_StringEntry( tw::STR_GENERATING_DB, _T("Generating the database...\n") ), + TSS_StringEntry( tw::STR_INIT_SUCCESS, _T("The database was successfully generated.\n") ), + TSS_StringEntry( tw::STR_FILE_WRITTEN, _T("File written: ") ), + TSS_StringEntry( tw::STR_FILE_OPEN, _T("Opening file: ") ), + TSS_StringEntry( tw::STR_FILE_ENCRYPTED, _T("This file is encrypted.\n") ), + TSS_StringEntry( tw::STR_OPEN_KEYFILE, _T("Opening key file: ") ), + TSS_StringEntry( tw::STR_OPEN_CONFIG_FILE, _T("Opening configuration file: ") ), + TSS_StringEntry( tw::STR_OPEN_DB_FILE, _T("Opening database file: ") ), + TSS_StringEntry( tw::STR_OPEN_REPORT_FILE, _T("Opening report file: ") ), + + TSS_StringEntry( tw::STR_REPORTEVENT_FAILED, _T("Unable to add event to Event Log. The Event Log may be full.") ), + TSS_StringEntry( tw::STR_SYSLOG_FAILED, _T("Unable to add event to Syslog.") ), + + TSS_StringEntry( tw::STR_WRITE_POLICY_FILE, _T("Wrote policy file: ") ), + TSS_StringEntry( tw::STR_WRITE_DB_FILE, _T("Wrote database file: ") ), + TSS_StringEntry( tw::STR_WRITE_REPORT_FILE, _T("Wrote report file: ") ), + TSS_StringEntry( tw::STR_WRITE_CONFIG_FILE, _T("Wrote configuration file: ") ), + + TSS_StringEntry( tw::STR_REPORT_TITLE, _T("Open Source Tripwire(R) 2.4.2.2 Integrity Check Report") ), + TSS_StringEntry( tw::STR_R_GENERATED_BY, _T("Report generated by: ") ), + TSS_StringEntry( tw::STR_R_CREATED_ON, _T("Report created on: ") ), + TSS_StringEntry( tw::STR_DB_CREATED_ON, _T("Database generated on: ") ), + TSS_StringEntry( tw::STR_DB_LAST_UPDATE, _T("Database last updated on: ") ), + TSS_StringEntry( tw::STR_R_SUMMARY, _T("Report Summary:") ), + TSS_StringEntry( tw::STR_HOST_NAME, _T("Host name:") ), + TSS_StringEntry( tw::STR_HOST_IP, _T("Host IP address:") ), + TSS_StringEntry( tw::STR_HOST_ID, _T("Host ID:") ), + TSS_StringEntry( tw::STR_POLICY_FILE_USED, _T("Policy file used: ") ), + TSS_StringEntry( tw::STR_CONFIG_FILE_USED, _T("Configuration file used: ") ), + TSS_StringEntry( tw::STR_DB_FILE_USED, _T("Database file used: ") ), + TSS_StringEntry( tw::STR_CMD_LINE_USED, _T("Command line used: ") ), + TSS_StringEntry( tw::STR_SEVERITY_LEVEL, _T("Severity Level") ), + TSS_StringEntry( tw::STR_TOTAL_VIOLATIONS, _T("Total violations found: ") ), + TSS_StringEntry( tw::STR_OBJECTS_SCANNED, _T("Total objects scanned: ") ), + TSS_StringEntry( tw::STR_SECTION, _T("Section") ), + + + TSS_StringEntry( tw::STR_ATTRIBUTES, _T("Property: ") ), + TSS_StringEntry( tw::STR_OBSERVED, _T("Observed") ), + TSS_StringEntry( tw::STR_EXPECTED, _T("Expected") ), + TSS_StringEntry( tw::STR_DB_UPDATE, _T("Database Update: ") ), + TSS_StringEntry( tw::STR_RULE_SUMMARY, _T("Rule Summary: ") ), + TSS_StringEntry( tw::STR_OBJECT_SUMMARY, _T("Object Summary: ") ), + TSS_StringEntry( tw::STR_OBJECT_DETAIL, _T("Object Detail: ") ), + TSS_StringEntry( tw::STR_RULE_NAME, _T("Rule Name") ), + TSS_StringEntry( tw::STR_ALL_RULE_NAMES, _T("Rules Used: ") ), + TSS_StringEntry( tw::STR_TOTAL_NUM_RULES, _T("Total number of rules used: ") ), + TSS_StringEntry( tw::STR_START_POINT, _T("Start Point: ") ), + TSS_StringEntry( tw::STR_ADDED, _T("Added") ), + TSS_StringEntry( tw::STR_REMOVED, _T("Removed") ), + TSS_StringEntry( tw::STR_CHANGED, _T("Modified") ), + TSS_StringEntry( tw::STR_ADDED_FILES, _T("Added Objects: ") ), + TSS_StringEntry( tw::STR_REMOVED_FILES, _T("Removed Objects: ") ), + TSS_StringEntry( tw::STR_CHANGED_FILES, _T("Modified Objects: ") ), + TSS_StringEntry( tw::STR_TOTAL_NUM_ADDED_FILES, _T("Total number of added objects: ") ), + TSS_StringEntry( tw::STR_TOTAL_NUM_REMOVED_FILES, _T("Total number of removed objects: ") ), + TSS_StringEntry( tw::STR_TOTAL_NUM_CHANGED_FILES, _T("Total number of modified objects: ") ), + TSS_StringEntry( tw::STR_OBJECT_NAME, _T("Object name: ") ), + TSS_StringEntry( tw::STR_ADDED_FILE_NAME, _T("Added object name: ") ), + TSS_StringEntry( tw::STR_REMOVED_FILE_NAME, _T("Removed object name: ") ), + TSS_StringEntry( tw::STR_CHANGED_FILE_NAME, _T("Modified object name: ") ), + TSS_StringEntry( tw::STR_ERROR_REPORT, _T("Error Report: ") ), + TSS_StringEntry( tw::STR_REPORT_NO_ERRORS, _T("No Errors") ), + TSS_StringEntry( tw::STR_NO_VIOLATIONS_IN_SECTION,_T("No violations.") ), + + TSS_StringEntry( tw::STR_ADD_X, _T("Remove the \"x\" from the adjacent box to prevent updating the database\nwith the new values for this object.") ), + TSS_StringEntry( tw::STR_UPDATE_ALL, _T("Update database with all modifications for rule: ") ), + + TSS_StringEntry( tw::STR_END_OF_REPORT, _T("*** End of report ***") ), + TSS_StringEntry( tw::STR_NONE, _T("None") ), + TSS_StringEntry( tw::STR_NEVER, _T("Never") ), + TSS_StringEntry( tw::STR_OBJECTS, _T("Objects") ), + TSS_StringEntry( tw::STR_TRIPWIRE_REPORT_SHORT, _T("TWReport") ), + TSS_StringEntry( tw::STR_VIOLATIONS_SHORT, _T("V") ), + TSS_StringEntry( tw::STR_MAX_SEV_SHORT, _T("S") ), + TSS_StringEntry( tw::STR_ADDED_SHORT, _T("A") ), + TSS_StringEntry( tw::STR_REMOVED_SHORT, _T("R") ), + TSS_StringEntry( tw::STR_CHANGED_SHORT, _T("C") ), + + TSS_StringEntry( tw::STR_DBPRINT_TITLE, _T("Open Source Tripwire(R) 2.4.2.2 Database") ), + TSS_StringEntry( tw::STR_DB_GENERATED_BY, _T("Database generated by: ") ), + TSS_StringEntry( tw::STR_TOTAL_NUM_FILES, _T("Total number of objects: ") ), + TSS_StringEntry( tw::STR_END_OF_DB, _T("*** End of database ***") ), + TSS_StringEntry( tw::STR_DB_SUMMARY, _T("Database Summary: ") ), + TSS_StringEntry( tw::STR_ATTR_VALUE, _T("Value: ") ), + + // twutil + TSS_StringEntry( tw::STR_IP_UNKNOWN, _T("Unknown IP") ), + + // twutil + TSS_StringEntry( tw::STR_ERR_NOT_FULL_PATH, _T("Object name is not fully qualified; skipping.") ), + TSS_StringEntry( tw::STR_ERR_OBJ_NOT_IN_DB, _T("Object not found in the database.") ), + TSS_StringEntry( tw::STR_ERR_DB_DOESNT_CONTAIN_GENRE, _T("Section not found in database.") ), + TSS_StringEntry( tw::STR_ERR2_CFG_KEY_MISMATCH1, _T("The config file \"") ), + TSS_StringEntry( tw::STR_ERR2_CFG_KEY_MISMATCH2, _T("\" is not encrypted with the current keyfile \"") ), + TSS_StringEntry( tw::STR_ERR2_CFG_KEY_MISMATCH3, _T("\".") ), + TSS_StringEntry( tw::STR_ERR_CFG_UNENCRYPTED, _T("Config file is unencrypted.") ), + TSS_StringEntry( tw::STR_ERR_POL_UNENCRYPTED, _T("Policy file is unencrypted.") ), + TSS_StringEntry( tw::STR_ERR_BACKUP_FAILED, _T("File Backup Failed.") ), + TSS_StringEntry( tw::STR_ERR2_BACKUP_FAILED1, _T("Error backing up \"") ), + TSS_StringEntry( tw::STR_ERR2_BACKUP_FAILED2, _T("\" to \"") ), + TSS_StringEntry( tw::STR_ERR2_BACKUP_FAILED3, _T("\".") ), + + // used for reporting errors when linked with console.exe or reportviewer.exe + TSS_StringEntry( tw::STR_MEMORY_MAPPED_FILENAME, _T("Memory Mapped File") ), + + // + // Version + // + TSS_StringEntry( tw::STR_COPYRIGHT, TSS_COPYRIGHT_NOTICE ), + TSS_StringEntry( tw::STR_TSS_PRODUCT_NAME, TSS_PRODUCT_NAME BUILD_NUM UNICODE_STR DEBUG_STR ), + + TSS_StringEntry( tw::STR_VERSION, TSS_PRODUCT_NAME BUILD_NUM UNICODE_STR DEBUG_STR _T(" built for "TARGET_OS"\n\n") TSS_COPYRIGHT_NOTICE ), + TSS_StringEntry( tw::STR_VERSION_LONG, TSS_PRODUCT_NAME BUILD_NUM UNICODE_STR DEBUG_STR _T(" built for "TARGET_OS"\n\n") TSS_COPYRIGHT_NOTICE_LONG ), + +TSS_EndStringtable( cTW ) + + +// eof: twstrings.cpp + diff --git a/src/tw/twstrings.h b/src/tw/twstrings.h new file mode 100644 index 0000000..f9c5fbd --- /dev/null +++ b/src/tw/twstrings.h @@ -0,0 +1,187 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twstrings.h +// Date....: 5/11/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __TWSTRINGS_H +#define __TWSTRINGS_H + +#include "tw.h" + +TSS_BeginStringIds( tw ) + STR_ERR_MISSING_LOCAL_KEY, + STR_ERR_MISSING_SITE_KEY, + STR_ERR_MISSING_POLICY, + STR_ERR_MISSING_DB, + STR_ERR_MISSING_REPORT, + STR_ERR_MISSING_EDITOR, + STR_GENERATING_DB, + STR_ERR_WRONG_PASSPHRASE_LOCAL, + STR_ERR_WRONG_PASSPHRASE_SITE, + STR_DEF_CFG_FILENAME, + STR_WIN_NT_ONLY, + STR_GET_HELP, + STR_VERSION, + STR_VERSION_LONG, + STR_NEWLINE, + STR_ERR_TWCFG_CANT_READ, + STR_ERR_NO_MODE, + STR_UNKOWN_MODE_SPECIFIED, + STR_ERR2_BAD_MODE_SWITCH, + STR_PARSING_POLICY, + STR_ERR_REPORT_READ, + STR_REPORT_NOT_ENCRYPTED, + STR_ERR_DB_READ, + STR_CUR_LINE, + STR_INIT_SUCCESS, + STR_REPORTEVENT_FAILED, + STR_SYSLOG_FAILED, + + STR_ENTER_LOCAL_PASSPHRASE, + STR_ENTER_SITE_PASSPHRASE, + STR_ENTER_PROVIDED_PASSPHRASE, + STR_DB_NOT_UPDATED, // db update not performed due to anal mode + STR_IGNORE_PROPS, // ignoring properties + STR_NOT_IMPLEMENTED, + STR_REPORT_EMPTY, + STR_FILE_WRITTEN, + STR_FILE_OPEN, + STR_FILE_ENCRYPTED, + STR_OPEN_KEYFILE, + STR_OPEN_CONFIG_FILE, + STR_OPEN_DB_FILE, + STR_OPEN_REPORT_FILE, + STR_OPEN_POLICY_FILE, + STR_WRITE_POLICY_FILE, + STR_WRITE_DB_FILE, + STR_WRITE_REPORT_FILE, + STR_WRITE_CONFIG_FILE, + + STR_REPORT_TITLE, + STR_R_GENERATED_BY, + STR_R_CREATED_ON, + STR_DB_CREATED_ON, + STR_DB_LAST_UPDATE, + STR_R_SUMMARY, + STR_HOST_NAME, + STR_HOST_IP, + STR_HOST_ID, + STR_POLICY_FILE_USED, + STR_CONFIG_FILE_USED, + STR_DB_FILE_USED, + STR_CMD_LINE_USED, + STR_SEVERITY_LEVEL, + STR_RULE_NAME, + STR_ALL_RULE_NAMES, + STR_TOTAL_NUM_RULES, + STR_START_POINT, + STR_TOTAL_VIOLATIONS, + STR_OBJECTS_SCANNED, + STR_SECTION, + STR_ATTRIBUTES, + STR_OBSERVED, + STR_EXPECTED, + STR_DB_UPDATE, + STR_RULE_SUMMARY, + STR_OBJECT_SUMMARY, + STR_OBJECT_DETAIL, + STR_ADDED, + STR_REMOVED, + STR_CHANGED, + STR_ADDED_FILES, + STR_REMOVED_FILES, + STR_CHANGED_FILES, + STR_TOTAL_NUM_ADDED_FILES, + STR_TOTAL_NUM_REMOVED_FILES, + STR_TOTAL_NUM_CHANGED_FILES, + STR_OBJECT_NAME, + STR_ADDED_FILE_NAME, + STR_REMOVED_FILE_NAME, + STR_CHANGED_FILE_NAME, + STR_ERROR_REPORT, + STR_REPORT_NO_ERRORS, + STR_NO_VIOLATIONS_IN_SECTION, + STR_ADD_X, + STR_UPDATE_ALL, + STR_END_OF_REPORT, + STR_NONE, + STR_NEVER, + STR_OBJECTS, + STR_TRIPWIRE_REPORT_SHORT, + STR_VIOLATIONS_SHORT, + STR_MAX_SEV_SHORT, + STR_ADDED_SHORT, + STR_REMOVED_SHORT, + STR_CHANGED_SHORT, + + // database strings + STR_DBPRINT_TITLE, + STR_DB_GENERATED_BY, + STR_TOTAL_NUM_FILES, + STR_END_OF_DB, + STR_DB_SUMMARY, + STR_ATTR_VALUE, + + // twutil + STR_IP_UNKNOWN, + + // twutil + STR_ERR_NOT_FULL_PATH, + STR_ERR_OBJ_NOT_IN_DB, + STR_ERR_DB_DOESNT_CONTAIN_GENRE, + STR_ERR2_CFG_KEY_MISMATCH1, + STR_ERR2_CFG_KEY_MISMATCH2, + STR_ERR2_CFG_KEY_MISMATCH3, + STR_ERR_CFG_UNENCRYPTED, + STR_ERR_POL_UNENCRYPTED, + STR_ERR_BACKUP_FAILED, + STR_ERR2_BACKUP_FAILED1, + STR_ERR2_BACKUP_FAILED2, + STR_ERR2_BACKUP_FAILED3, + + // used for reporting errors when linked with console.exe or reportviewer.exe + STR_MEMORY_MAPPED_FILENAME, + + STR_COPYRIGHT, + STR_TSS_PRODUCT_NAME + +TSS_EndStringIds( tw ) + +// Get strings like this: +// TSS_GetString( cTW, tw::STR_NOTIFY_GEN_SIG ).c_str(), + +#endif//__TWSTRINGS_H + diff --git a/src/tw/twutil.cpp b/src/tw/twutil.cpp new file mode 100644 index 0000000..04d5d7d --- /dev/null +++ b/src/tw/twutil.cpp @@ -0,0 +1,1491 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twutil.cpp +// + +#include "stdtw.h" +#include "twutil.h" + +#include "twcrypto/crypto.h" +#include "core/archive.h" +#include "core/serializerimpl.h" +#include "twcrypto/cryptoarchive.h" +#include "fcoreport.h" +#include "twcrypto/keyfile.h" +#include "fco/fcospeclist.h" +#include "fco/genreswitcher.h" +#include "core/errorbucketimpl.h" +#include "core/cmdlineparser.h" +#include "configfile.h" +#include "core/fileheader.h" +#include "core/usernotify.h" +#include "policyfile.h" +#include "core/serstring.h" +#include "headerinfo.h" +#include "systeminfo.h" +#include "core/errorgeneral.h" +#include "fco/parsergenreutil.h" +#include "fco/twfactory.h" +#include "fco/fconame.h" +#include "fcodatabasefile.h" +#include "util/fileutil.h" +#include "core/stringutil.h" +#include "tw/twstrings.h" +#include "tw/twerrors.h" +#include "core/ntmbs.h" +#include "core/displayencoder.h" + +#ifdef TW_PROFILE +#include "core/tasktimer.h" +#endif + +#include "core/fsservices.h" // for the util_IsDir() stuff + +#if IS_UNIX +#include +#include +#include +#include +#include "core/tw_signal.h" +int _getch(void); +#endif + +#ifdef _UNICODE // right now we only need this for unicode +#include +#endif + +// constants +static const char* POLICY_FILE_MAGIC_8BYTE = "#POLTXT\n"; +static const char* CONFIG_FILE_MAGIC_8BYTE = "#CFGTXT\n"; +static const uint32 CURRENT_FIXED_VERSION = 0x02020000; + + +/////////////////////////////////////////////////////////////////////////////// +// WriteObjectToArchive -- called from WriteObject, does most of the work +/////////////////////////////////////////////////////////////////////////////// +static void WriteObjectToArchive(cArchive &arch, const TCHAR* filename, // filename is used only for issuing error messages + const iTypedSerializable* pObjHeader, const iTypedSerializable& obj, + cFileHeader& fileHeader, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + try + { + // Set file version. + // If we in the future we wish to support reading databases of different versions, + // we will have to move this set to outside WriteObject(). + fileHeader.SetVersion(CURRENT_FIXED_VERSION); + + fileHeader.SetEncoding(bEncrypt ? cFileHeader::ASYM_ENCRYPTION : cFileHeader::COMPRESSED); + + { + cSerializerImpl fhSer(arch, cSerializerImpl::S_WRITE, filename); + fileHeader.Write(&fhSer); + } + + if (bEncrypt) + { + cElGamalSigArchive cryptoArchive; + cryptoArchive.SetWrite(&arch, pPrivateKey); + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_WRITE, filename); + ser.Init(); + if(pObjHeader) + ser.WriteObject(pObjHeader); + ser.WriteObject(&obj); + ser.Finit(); + cryptoArchive.FlushWrite(); + } + else + { + // not encrypted + cNullCryptoArchive cryptoArchive; + cryptoArchive.Start(&arch); + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_WRITE, filename); + ser.Init(); + if(pObjHeader) + ser.WriteObject(pObjHeader); + ser.WriteObject(&obj); + ser.Finit(); + cryptoArchive.Finish(); + } + + } + catch (eError& e) + { + throw ePoly( + e.GetID(), + cErrorUtil::MakeFileError( e.GetMsg(), filename ), + e.GetFlags() ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// WriteObject -- template class that writes an object to disk (ie -- report, +// db, etc) either encrypted or unencrypted. +// The only requrement on the object is that it is typed serializable. +// errorMsg is a number that can be passed to iUserString to indicate an +// appropriate error message if the object fails to load +// +// 10/30 -- this function has been expanded to take two objects -- a header and +// an object. Both are typed serializable, but the header can be NULL if +// none is desired. +/////////////////////////////////////////////////////////////////////////////// +static void WriteObject(const TCHAR* filename, const iTypedSerializable* pObjHeader, const iTypedSerializable& obj, + cFileHeader& fileHeader, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cDebug d("WriteObject"); + d.TraceDebug(_T("Writing %s to file %s\n"), obj.GetType().AsString(), filename); + + ASSERT(pPrivateKey || (! bEncrypt)); + + cFileArchive arch; + + if (!cFileUtil::IsRegularFile(filename) && cFileUtil::FileExists(filename)) + throw eArchiveNotRegularFile( filename ); + + try + { + arch.OpenReadWrite( filename ); + } + catch (eArchive&) + { + // probably better to rethrow this as a write failed exception + throw eArchiveWrite( filename, iFSServices::GetInstance()->GetErrString() ) ; + } + + WriteObjectToArchive(arch, filename, pObjHeader, obj, fileHeader, bEncrypt, pPrivateKey); + + arch.Close(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// WriteObjectToArchive -- called from WriteObject, does most of the work +/////////////////////////////////////////////////////////////////////////////// +static void ReadObjectFromArchive(cArchive &arch, const TCHAR* objFileName, iTypedSerializable* pObjHeader, iTypedSerializable& obj, const cFileHeaderID& fhid, const cElGamalSigPublicKey* pPublicKey, bool& bEncrypted) +{ + cFileHeader fileHeader; + + { + cSerializerImpl fhSer(arch, cSerializerImpl::S_READ, objFileName); + fileHeader.Read(&fhSer); + } + + // check for a mismatched header + if (fileHeader.GetID() != fhid) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), objFileName, eSerializer::TY_FILE)); + + // Check file version. + // If we in the future we wish to support reading objects of different versions, + // we will have to move this check to outside ReadObject(). + if (fileHeader.GetVersion() != CURRENT_FIXED_VERSION) + ThrowAndAssert(eSerializerVersionMismatch(_T(""), objFileName, eSerializer::TY_FILE)); + + try + { + // switch on the type of encoding... + if(fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + // tell the user the db is encrypted + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString( cTW, tw::STR_FILE_ENCRYPTED).c_str()); + bEncrypted = true; + + if (pPublicKey == 0) + ThrowAndAssert(eSerializerEncryption(_T(""))); + + cElGamalSigArchive cryptoArchive; + cryptoArchive.SetRead(&arch, pPublicKey); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ, objFileName); + ser.Init(); + if(pObjHeader) + ser.ReadObject(pObjHeader); + ser.ReadObject(&obj); + ser.Finit(); + } + else if(fileHeader.GetEncoding() == cFileHeader::COMPRESSED) + { + //not encrypted db... + bEncrypted = false; + + cNullCryptoArchive cryptoArchive; + cryptoArchive.Start(&arch); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ, objFileName); + ser.Init(); + if(pObjHeader) + ser.ReadObject(pObjHeader); + ser.ReadObject(&obj); + ser.Finit(); + } + else + // unknown encoding... + ThrowAndAssert(eSerializerInputStreamFmt(_T(""))); + } + catch (eError& e) + { + // include filename in error msg + throw ePoly( + e.GetID(), + cErrorUtil::MakeFileError( e.GetMsg(), objFileName ), + e.GetFlags() ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadObject -- writes an object from disk, either encrypted or not, that was +// written using WriteObject above. +/////////////////////////////////////////////////////////////////////////////// +static void ReadObject(const TCHAR* objFileName, iTypedSerializable* pObjHeader, iTypedSerializable& obj, const cFileHeaderID& fhid, const cElGamalSigPublicKey* pPublicKey, bool& bEncrypted) +{ + cDebug d("ReadObject"); + d.TraceDebug(_T("Reading %s from file %s\n"), obj.GetType().AsString(), objFileName); + + cFileArchive arch; + arch.OpenRead( objFileName ); + + ReadObjectFromArchive(arch, objFileName, pObjHeader, obj, fhid, pPublicKey, bEncrypted); + +} + +/////////////////////////////////////////////////////////////////////////////// +// IsObjectEncrypted +/////////////////////////////////////////////////////////////////////////////// +bool cTWUtil::IsObjectEncrypted( const TCHAR* objFileName, const cFileHeaderID& fhid, const TSTRING& errorMsg ) +{ + bool fEncrypted = false; + cDebug d("IsObjectEncrypted"); + d.TraceDebug(_T("Reading from file %s\n"), objFileName); + + try + { + cFileArchive arch; + arch.OpenRead( objFileName ); + + cFileHeader fileHeader; + cSerializerImpl fhSer(arch, cSerializerImpl::S_READ, objFileName); + fileHeader.Read(&fhSer); + + // check for a mismatched header + if (fileHeader.GetID() != fhid) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), objFileName, eSerializer::TY_FILE)); + + // switch on the type of encoding... + if(fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + fEncrypted = true; + } + else if(fileHeader.GetEncoding() == cFileHeader::COMPRESSED) + { + fEncrypted = false; + } + else + // unknown encoding... + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), objFileName, eSerializer::TY_FILE)); + } + catch(eArchive& e) + { + // Note: Output to TCERR is O.K. here, it is documented that this is what this function does + TSTRING msg = e.GetMsg(); + if( ! msg.empty() ) + msg += _T("\n"); + msg += errorMsg; + + cTWUtil::PrintErrorMsg(ePoly(e.GetID(), msg, e.GetFlags() )); + ThrowAndAssert(ePoly()); + } + catch(eSerializer& e) + { + // Note: Output to TCERR is O.K. here, it is documented that this is what this function does + TSTRING msg = e.GetMsg(); + if( ! msg.empty() ) + msg += _T("\n"); + msg += errorMsg; + + cTWUtil::PrintErrorMsg(ePoly(e.GetID(), msg, e.GetFlags() )); + ThrowAndAssert(ePoly()); + } + + return( fEncrypted ); +} + +bool cTWUtil::IsObjectEncrypted( cArchive &arch, const cFileHeaderID& fhid, const TSTRING& errorMsg ) +{ + bool fEncrypted = false; + cDebug d("IsObjectEncrypted"); + d.TraceDebug(_T("Reading from archive\n")); + + try + { + cFileHeader fileHeader; + cSerializerImpl fhSer(arch, cSerializerImpl::S_READ, TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME).c_str()); + fileHeader.Read(&fhSer); + + // check for a mismatched header + if (fileHeader.GetID() != fhid) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME).c_str(), eSerializer::TY_FILE)); + + // switch on the type of encoding... + if(fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + fEncrypted = true; + } + else if(fileHeader.GetEncoding() == cFileHeader::COMPRESSED) + { + fEncrypted = false; + } + else + // unknown encoding... + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME).c_str(), eSerializer::TY_FILE)); + } + catch(eArchive& e) + { + // Note: Output to TCERR is O.K. here, it is documented that this is what this function does + TSTRING msg = e.GetMsg(); + if( ! msg.empty() ) + msg += _T("\n"); + msg += errorMsg; + + cTWUtil::PrintErrorMsg(ePoly(e.GetID(), msg, e.GetFlags() )); + ThrowAndAssert(ePoly()); + } + catch(eSerializer& e) + { + // Note: Output to TCERR is O.K. here, it is documented that this is what this function does + TSTRING msg = e.GetMsg(); + if( ! msg.empty() ) + msg += _T("\n"); + msg += errorMsg; + + cTWUtil::PrintErrorMsg(ePoly(e.GetID(), msg, e.GetFlags() )); + ThrowAndAssert(ePoly()); + } + + return( fEncrypted ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// WriteDatabase +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::WriteDatabase(const TCHAR* filename, cFCODatabaseFile& db, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cFileHeader fileHeader; + fileHeader.SetID(db.GetFileHeaderID()); + + // I am almost positive that this does nothing, WriteObject() sets the version in the cFileHeader - Jun 8, 1999 - dmb + //fileHeader.SetVersion(1); + +#ifdef TW_PROFILE + cWin32TaskTimer timer(_T("Write Database")); + timer.Start(); +#endif + + WriteObject(filename, 0, db, fileHeader, bEncrypt, pPrivateKey); + +#ifdef TW_PROFILE + timer.Stop(); +#endif + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_DB_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadDatabase +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::ReadDatabase(const TCHAR* filename, cFCODatabaseFile& db, const cElGamalSigPublicKey* pPublicKey, bool& bEncrypted) +{ + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_DB_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); + +#ifdef TW_PROFILE + cWin32TaskTimer timer("cTWUtil::ReadDatabase"); + timer.Start(); +#endif + + ReadObject(filename, 0, db, cFCODatabaseFile::GetFileHeaderID(), pPublicKey, bEncrypted); + +#ifdef TW_PROFILE + timer.Stop(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// WriteReport +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::WriteReport(const TCHAR* filename, const cFCOReportHeader& reportHeader, const cFCOReport& r, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cFileHeader fileHeader; + fileHeader.SetID(cFCOReport::GetFileHeaderID()); + + WriteObject(filename, &reportHeader, r, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_REPORT_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); +} + + +void cTWUtil::WriteReport(cArchive &archive, const cFCOReportHeader& reportHeader, const cFCOReport& r, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cFileHeader fileHeader; + fileHeader.SetID(cFCOReport::GetFileHeaderID()); + + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + WriteObjectToArchive(archive, filename.c_str(), &reportHeader, r, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_REPORT_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadReport +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::ReadReport(const TCHAR* reportFileName, cFCOReportHeader& reportHeader, cFCOReport& r, const cElGamalSigPublicKey* pPublicKey, bool silent, bool& bEncrypted) +{ + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_REPORT_FILE).c_str(), + cDisplayEncoder::EncodeInline( reportFileName ).c_str() ); + + ReadObject(reportFileName, &reportHeader, r, cFCOReport::GetFileHeaderID(), pPublicKey, bEncrypted); +} + +void cTWUtil::ReadReport(cArchive &archive, cFCOReportHeader& reportHeader, cFCOReport& r, const cElGamalSigPublicKey* pPublicKey, bool silent, bool& bEncrypted) +{ + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_REPORT_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str()); + + ReadObjectFromArchive(archive, filename.c_str(), &reportHeader, r, cFCOReport::GetFileHeaderID(), pPublicKey, bEncrypted); +} + +/////////////////////////////////////////////////////////////////////////////// +// UpdatePolicyFile +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::UpdatePolicyFile(const TCHAR* destFileName, const TCHAR* srcFileName, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cFileArchive src; + src.OpenRead(srcFileName); // note: eArchive may float up + + std::string policyText; + policyText.resize(src.Length()); + + src.ReadBlob((void*)policyText.data(), src.Length()); + + // NOTE -- this method will emit a message to stdout when the file has been written + cTWUtil::WritePolicyText(destFileName, policyText, bEncrypt, pPrivateKey); +} + +TSTRING cTWUtil::GetCfgFilePath(const cCmdLineParser& cmdLine, int cfgFileID) +{ + + TSTRING cfgFilePath; + bool fConfigOnCmdLine = false; + + // let's see if this was specified on the command line... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + if(iter.ArgId() == cfgFileID) + { + ASSERT(iter.NumParams() > 0); + cfgFilePath = iter.ParamAt(0); + fConfigOnCmdLine = true; + } + } + + // OK, now we need to figure out where to find the config file. + // If the location was specified on the command line, get the full path to it. + // otherwise, the location is the dir that this exe is in. + if( fConfigOnCmdLine ) + { + TSTRING pathOut; + iFSServices::GetInstance()->FullPath( pathOut, cfgFilePath ) ; + cfgFilePath = pathOut; + } + else + { + iFSServices::GetInstance()->FullPath( cfgFilePath, TSS_GetString(cTW, tw::STR_DEF_CFG_FILENAME), + cSystemInfo::GetExeDir() ) ; + } + + + cFileUtil::TestFileExists(cfgFilePath); + + + return (cfgFilePath); +} + +/////////////////////////////////////////////////////////////////////////////// +// OpenConfigFile -- opens the config file, either from a known location or +// from the location specified on the command line. Returns false if it fails. +// cfgFileID is the ID of the config file switch +// TODO -- should this guy spit the error to cerr or fill up an error bucket? +///////////////////////////////////////////////////////////////////////////////// +void cTWUtil::OpenConfigFile(cConfigFile& cf, cCmdLineParser& cmdLine, int cfgFileID, cErrorBucket& errorBucket, TSTRING& configFileOut) +{ + + configFileOut = GetCfgFilePath(cmdLine, cfgFileID); + + // ok, now let's load it! + TSTRING configText; + cTWUtil::ReadConfigText(configFileOut.c_str(), configText); + cf.ReadString( configText ); +} + +/////////////////////////////////////////////////////////////////////////////// +// WriteConfigText +// eArchive is thrown if filename can not be opened +// eSerializer is thrown if reading or writing fails + +void cTWUtil::WriteConfigText(const TCHAR* filename, const TSTRING configText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cSerializableNString nstring; + + nstring.mString = CONFIG_FILE_MAGIC_8BYTE; + + std::string ns; + cStringUtil::Convert( ns, configText ); + nstring.mString += ns; + + cFileHeader fileHeader; + fileHeader.SetID(cConfigFile::GetFileHeaderID()); + + fileHeader.SetVersion(CURRENT_FIXED_VERSION); + + if (bEncrypt) + { + ASSERT(pPrivateKey != 0); + cElGamalSigPublicKey publicKey(*pPrivateKey); + fileHeader.GetBaggage().MapArchive(0, publicKey.GetWriteLen()); + publicKey.Write(fileHeader.GetBaggage().GetMap()); + } + + WriteObject(filename, NULL, nstring, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_CONFIG_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); +} + +void cTWUtil::WriteConfigText(cArchive &archive, const TSTRING configText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cSerializableNString nstring; + + nstring.mString = CONFIG_FILE_MAGIC_8BYTE; + + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + std::string ns; + cStringUtil::Convert( ns, configText ); + nstring.mString += ns; + + cFileHeader fileHeader; + fileHeader.SetID(cConfigFile::GetFileHeaderID()); + + fileHeader.SetVersion(CURRENT_FIXED_VERSION); + + if (bEncrypt) + { + ASSERT(pPrivateKey != 0); + cElGamalSigPublicKey publicKey(*pPrivateKey); + fileHeader.GetBaggage().MapArchive(0, publicKey.GetWriteLen()); + publicKey.Write(fileHeader.GetBaggage().GetMap()); + } + + WriteObjectToArchive(archive, filename.c_str(), NULL, nstring, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_CONFIG_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str()); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ReadConfigText +// eArchive is thrown if filename can not be opened +// eSerializer is thrown if reading or writing fails +// eConfigFile is thrown if config file does not parse correctly during reading + +void cTWUtil::ReadConfigText(const TCHAR* filename, TSTRING& configText, cArchive* pBaggage) +{ +// TODO -- neat up this function; try to use LoadObject() above... + + cSerializableNString nstring; + + // This was coppied from ReadObject(). We need to use the baggage of the + // file header to obtain the public key, thus the special casing. + cDebug d("ReadConfigText"); + d.TraceDebug(_T("Reading %s from file %s\n"), nstring.GetType().AsString(), filename); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_CONFIG_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); + + cFileArchive arch; + arch.OpenRead( filename ); + + cFileHeader fileHeader; + + try + { + cSerializerImpl fhSer(arch, cSerializerImpl::S_READ); + fileHeader.Read(&fhSer); + } + catch (eError&) + { + throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE); + } + +#if 0 // XXX: This is broken, what the h*ll are they trying to write here? -PH + d.TraceDebug("Found a file header of type %d.\n", fileHeader.GetEncoding()); +#endif + + // check for a mismatched header + if (fileHeader.GetID() != cConfigFile::GetFileHeaderID()) + throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE); + + // check the version + if (fileHeader.GetVersion() != CURRENT_FIXED_VERSION) + throw eSerializerVersionMismatch(_T(""), filename, eSerializer::TY_FILE); + + // switch on the type of encoding... + if(fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + d.TraceDebug("Config file is compressed, public key len %d.\n", fileHeader.GetBaggage().Length()); + + // tell the user the db is encrypted + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_FILE_ENCRYPTED).c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + + ASSERT(fileHeader.GetBaggage().Length() > 0); + if (fileHeader.GetBaggage().Length() <= 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE)); + + fileHeader.GetBaggage().MapArchive(0, fileHeader.GetBaggage().Length()); + + cElGamalSigPublicKey publicKey(fileHeader.GetBaggage().GetMap()); + + cElGamalSigArchive cryptoArchive; + cryptoArchive.SetRead(&arch, &publicKey); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ); + ser.Init(); + ser.ReadObject(&nstring); + ser.Finit(); + + // copy the baggage into the archive, if it was passed in + // Note: We rely in VerifySiteKey that we only fill out pBaggage if + // the config file is encrypted. + // + if( pBaggage ) + { + fileHeader.GetBaggage().Seek( 0, cBidirArchive::BEGINNING ); + pBaggage->Copy( &fileHeader.GetBaggage(), fileHeader.GetBaggage().Length() ); + } + } + else if(fileHeader.GetEncoding() == cFileHeader::COMPRESSED) + { + d.TraceDebug("Config file is not compressed.\n"); + + //not encrypted db... + cNullCryptoArchive cryptoArchive; + cryptoArchive.Start(&arch); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ); + ser.Init(); + ser.ReadObject(&nstring); + ser.Finit(); + } + else + // unknown encoding... + throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE); + + // check 8 byte header + if (nstring.mString.compare(0, 8*sizeof(byte), CONFIG_FILE_MAGIC_8BYTE) != 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE)); + + // remove 8 byte header + nstring.mString.assign(nstring.mString.substr(8)); + + cStringUtil::Convert( configText, nstring.mString ); +} + + +void cTWUtil::ReadConfigText(cArchive &arch, TSTRING& configText, cArchive* pBaggage) +{ +// TODO -- neat up this function; try to use LoadObject() above... + + cSerializableNString nstring; + + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + // This was coppied from ReadObject(). We need to use the baggage of the + // file header to obtain the public key, thus the special casing. + cDebug d("ReadConfigText"); + d.TraceDebug(_T("Reading %s from file %s\n"), nstring.GetType().AsString(), filename.c_str()); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_CONFIG_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str()); + + + cFileHeader fileHeader; + + try + { + cSerializerImpl fhSer(arch, cSerializerImpl::S_READ); + fileHeader.Read(&fhSer); + } + catch (eError&) + { + throw eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE); + } + +#if 0 // XXX: This is broken, how can you convert a class to an int??? -PH + d.TraceDebug("Found a file header of type %d.\n", fileHeader.GetEncoding()); +#endif + + // check for a mismatched header + if (fileHeader.GetID() != cConfigFile::GetFileHeaderID()) + throw eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE); + + // check the version + if (fileHeader.GetVersion() != CURRENT_FIXED_VERSION) + throw eSerializerVersionMismatch(_T(""), filename.c_str(), eSerializer::TY_FILE); + + // switch on the type of encoding... + if(fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + d.TraceDebug("Config file is compressed, public key len %d.\n", fileHeader.GetBaggage().Length()); + + // tell the user the db is encrypted + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_FILE_ENCRYPTED).c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + + ASSERT(fileHeader.GetBaggage().Length() > 0); + if (fileHeader.GetBaggage().Length() <= 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE)); + + fileHeader.GetBaggage().MapArchive(0, fileHeader.GetBaggage().Length()); + + cElGamalSigPublicKey publicKey(fileHeader.GetBaggage().GetMap()); + + cElGamalSigArchive cryptoArchive; + cryptoArchive.SetRead(&arch, &publicKey); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ); + ser.Init(); + ser.ReadObject(&nstring); + ser.Finit(); + + // copy the baggage into the archive, if it was passed in + // Note: We rely in VerifySiteKey that we only fill out pBaggage if + // the config file is encrypted. + // + if( pBaggage ) + { + fileHeader.GetBaggage().Seek( 0, cBidirArchive::BEGINNING ); + pBaggage->Copy( &fileHeader.GetBaggage(), fileHeader.GetBaggage().Length() ); + } + } + else if(fileHeader.GetEncoding() == cFileHeader::COMPRESSED) + { + d.TraceDebug("Config file is not compressed.\n"); + + //not encrypted db... + cNullCryptoArchive cryptoArchive; + cryptoArchive.Start(&arch); + + cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ); + ser.Init(); + ser.ReadObject(&nstring); + ser.Finit(); + } + else + // unknown encoding... + throw eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE); + + // check 8 byte header + if (nstring.mString.compare(0, 8*sizeof(byte), CONFIG_FILE_MAGIC_8BYTE) != 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE)); + + // remove 8 byte header + nstring.mString.assign(nstring.mString.substr(8)); + + cStringUtil::Convert( configText, nstring.mString ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Given a filename and the text of a policy file, write an encrypted version +// of the policy file text to disk. +// Will throw eError on failure. + +void cTWUtil::WritePolicyText(const TCHAR* filename, const std::string polText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cSerializableNString nstring; + + // add a 8 byte header we can use to verify decryption + nstring.mString = POLICY_FILE_MAGIC_8BYTE; + + nstring.mString += polText; + + cFileHeader fileHeader; + fileHeader.SetID(cPolicyFile::GetFileHeaderID()); + + WriteObject(filename, NULL, nstring, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_POLICY_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str() ); +} + +void cTWUtil::WritePolicyText(cArchive &archive, const std::string polText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey) +{ + cSerializableNString nstring; + + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + // add a 8 byte header we can use to verify decryption + nstring.mString = POLICY_FILE_MAGIC_8BYTE; + + nstring.mString += polText; + + cFileHeader fileHeader; + fileHeader.SetID(cPolicyFile::GetFileHeaderID()); + + WriteObjectToArchive(archive, filename.c_str(), NULL, nstring, fileHeader, bEncrypt, pPrivateKey); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_WRITE_POLICY_FILE).c_str(), + cDisplayEncoder::EncodeInline( filename ).c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadPolicyText +// +// Read the policy file. Read the text of a policy language into configText +// Will throw eError on failure. +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::ReadPolicyText(const TCHAR* filename, std::string& polText, const cElGamalSigPublicKey* pPublicKey) +{ + cSerializableNString nstring; + + cFileUtil::TestFileExists(filename); + + bool bEncrypted; + ReadObject(filename, NULL, nstring, cPolicyFile::GetFileHeaderID(), pPublicKey, bEncrypted); + + // check 8 byte header + if (nstring.mString.compare(0, 8*sizeof(byte), POLICY_FILE_MAGIC_8BYTE) != 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE)); + + // remove 8 byte header + nstring.mString.assign(nstring.mString.substr(8)); + + polText = nstring.mString; +} + +void cTWUtil::ReadPolicyText(cArchive &archive, std::string& polText, const cElGamalSigPublicKey* pPublicKey) +{ + cSerializableNString nstring; + + TSTRING filename = TSS_GetString( cTW, tw::STR_MEMORY_MAPPED_FILENAME); + + bool bEncrypted; + ReadObjectFromArchive(archive, filename.c_str(), NULL, nstring, cPolicyFile::GetFileHeaderID(), pPublicKey, bEncrypted); + + // check 8 byte header + if (nstring.mString.compare(0, 8*sizeof(byte), POLICY_FILE_MAGIC_8BYTE) != 0) + ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename.c_str(), eSerializer::TY_FILE)); + + // remove 8 byte header + nstring.mString.assign(nstring.mString.substr(8)); + + polText = nstring.mString; +} + +/////////////////////////////////////////////////////////////////////////////// +// OpenKeyFile +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::OpenKeyFile(cKeyFile& keyFile, TSTRING fileName) +{ + // first, make sure the file exists... + cFileUtil::TestFileExists(fileName); + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString( cTW, tw::STR_OPEN_KEYFILE).c_str(), + cDisplayEncoder::EncodeInline( fileName ).c_str()); + + keyFile.ReadFile(fileName.c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// +// CreatePrivateKey +// we will attempt to get the correct passphrase three times before we +// give up. +/////////////////////////////////////////////////////////////////////////////// +const cElGamalSigPrivateKey* cTWUtil::CreatePrivateKey(cKeyFile& keyFile, const WCHAR16* usePassphrase, KeyType keyType, int nSecs) +{ + ASSERT(keyType == KEY_SITE || keyType == KEY_LOCAL || keyType == KEY_PROVIDED); + + const cElGamalSigPrivateKey* pPrivateKey = NULL; + wc16_string passphrase; + + if ( usePassphrase ) + { + // sleep to hinder brute force (dictionary, etc.) attacks + iFSServices::GetInstance()->Sleep( nSecs ); + + passphrase = usePassphrase; + + #ifndef WORDS_BIGENDIAN + passphrase.swapbytes(); + #endif + + pPrivateKey = keyFile.GetPrivateKey((int8*)passphrase.data(), passphrase.length() * sizeof(WCHAR16)); + + if(pPrivateKey) + return pPrivateKey; + + // if we got here, then a passphrase was provided on the command line that + // was not correct; this is an error condition. + // + if( keyType == KEY_LOCAL ) + throw eTWUtilBadPassLocal(); + else + throw eTWUtilBadPassSite(); + } + + int count = 0; + while(count < 3) + { + cTWUtil::NoEcho noEcho; + switch (keyType) + { + case KEY_LOCAL: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_LOCAL_PASSPHRASE); + break; + case KEY_SITE: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_SITE_PASSPHRASE); + break; + case KEY_PROVIDED: + default: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_PROVIDED_PASSPHRASE); + break; + } + + cTWUtil::GetString(passphrase); + TCOUT << std::endl; + + // sleep to hinder brute force (dictionary, etc.) attacks + iFSServices::GetInstance()->Sleep( nSecs ); + + #ifndef WORDS_BIGENDIAN + passphrase.swapbytes(); + #endif + + pPrivateKey = keyFile.GetPrivateKey((int8*)passphrase.data(), passphrase.length() * sizeof(WCHAR16)); + + if (pPrivateKey) + break; + + // tell the user that they entered the wrong passphrase + int strId = (keyType==KEY_LOCAL) ? tw::STR_ERR_WRONG_PASSPHRASE_LOCAL : + tw::STR_ERR_WRONG_PASSPHRASE_SITE; + TCOUT << TSS_GetString( cTW, strId) << std::endl; + passphrase.resize(0); + count++; + } + + if(! pPrivateKey) + throw ePoly(); + + return pPrivateKey; +} + +void cTWUtil::CreatePrivateKey(cPrivateKeyProxy& proxy, cKeyFile& keyFile, const WCHAR16* usePassphrase, KeyType keyType, int nSecs) +{ + ASSERT(keyType == KEY_SITE || keyType == KEY_LOCAL || keyType == KEY_PROVIDED); + + wc16_string passphrase; + + if (usePassphrase != 0) + { + // sleep to hinder brute force (dictionary, etc.) attacks + iFSServices::GetInstance()->Sleep( nSecs ); + + passphrase = usePassphrase; + + #ifndef WORDS_BIGENDIAN + passphrase.swapbytes(); + #endif + + if (proxy.AquireKey(keyFile, (int8*)passphrase.data(), passphrase.length() * sizeof(WCHAR16))) + return; + + // if we got here, then a passphrase was provided on the command line that + // was not correct; this is an error condition. + // + if( keyType == KEY_LOCAL ) + throw eTWUtilBadPassLocal(); + else + throw eTWUtilBadPassSite(); + } + + int count = 0; + while(count < 3) + { + cTWUtil::NoEcho noEcho; + switch (keyType) + { + case KEY_LOCAL: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_LOCAL_PASSPHRASE); + break; + case KEY_SITE: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_SITE_PASSPHRASE); + break; + case KEY_PROVIDED: + default: + TCOUT << TSS_GetString( cTW, tw::STR_ENTER_PROVIDED_PASSPHRASE); + break; + } + + cTWUtil::GetString(passphrase); + TCOUT << std::endl; + + // sleep to hinder brute force (dictionary, etc.) attacks + iFSServices::GetInstance()->Sleep( nSecs ); + + #ifndef WORDS_BIGENDIAN + passphrase.swapbytes(); + #endif + + if (proxy.AquireKey(keyFile, (int8*)passphrase.data(), passphrase.length() * sizeof(WCHAR16))) + return; + + // tell the user that they entered the wrong passphrase + int strId = (keyType==KEY_LOCAL) ? tw::STR_ERR_WRONG_PASSPHRASE_LOCAL : + (keyType==KEY_SITE) ? tw::STR_ERR_WRONG_PASSPHRASE_SITE : + tw::STR_ERR_WRONG_PASSPHRASE_LOCAL; // TODO: make this provided + + TCOUT << TSS_GetString( cTW, strId) << std::endl; + passphrase.resize(0); + count++; + } + + throw ePoly(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetStringNoEcho -- Get a string from the user without echoing it +/////////////////////////////////////////////////////////////////////////////// + + +#if IS_UNIX +static void (*old_SIGINT)(int); +static void (*old_SIGQUIT)(int); +static struct termios Otty; + +static void RestoreEcho(int sig) +{ +#ifdef _DEBUG + std::cout << "Caught signal, resetting echo."<< std::endl; + sleep(2); +#endif + + tcsetattr( 0, TCSAFLUSH, &Otty); + tw_signal(SIGINT, old_SIGINT); + tw_signal(SIGQUIT, old_SIGQUIT); + + tw_raise(sig); +} + +void cTWUtil::GetString(wc16_string& ret) +{ +#ifdef _UNICODE +#error We depend on Unix not being Unicode +#endif + + // get the string + const int MAX_STRING = 1024; + char buf[MAX_STRING]; + int len; + + TCOUT.flush(); + len = read( 0, buf, MAX_STRING ); + + // TODO:BAM -- mb-enable this! + if (len < MAX_STRING - 1) + buf[len] = 0; + + char* psz = tss::strdec( buf, buf + len ); + if ( *psz == '\n') + *psz = 0; + + ret = cStringUtil::TstrToWstr( buf ); +} + + +cTWUtil::NoEcho::NoEcho() +{ + // set the terminal to no echo mode + static struct termios Ntty; + + fflush(stdout); + tcgetattr( 0, &Otty); + Ntty = Otty; + + Ntty.c_lflag &= ~ECHO; + + // catch SIGINT and SIGQUIT + old_SIGINT = tw_signal(SIGINT, RestoreEcho); + old_SIGQUIT = tw_signal(SIGQUIT, RestoreEcho); + + if (tcsetattr( 0, TCSAFLUSH, &Ntty) != 0 && isatty(0)) + { + ThrowAndAssert(eTWUtilEchoModeSet()); + } +} + +cTWUtil::NoEcho::~NoEcho() { + tcsetattr( 0, TCSAFLUSH, &Otty); + tw_signal(SIGINT, old_SIGINT); + tw_signal(SIGQUIT, old_SIGQUIT); +} + +void cTWUtil::GetStringNoEcho(wc16_string& ret) +{ + NoEcho noEcho; + GetString(ret); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// ParseObjectList +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::ParseObjectList( cTWUtil::GenreObjList& listOut, const cTWUtil::ObjList& listIn ) +{ + + cGenre::Genre curGenre = cGenreSwitcher::GetInstance()->GetDefaultGenre(); + + ASSERT( listIn.size() > 0 ); + listOut.clear(); + GenreObjList::iterator curIter = listOut.end(); + cGenre::Genre iterGenre = cGenre::GENRE_INVALID; + + // iterate over all of the input... + // + for( ObjList::const_iterator i = listIn.begin(); i != listIn.end(); i++ ) + { + // first, try to interperate the current string as a genre name... + // 17 Mar 99 mdb -- we now only do this if the string ends in a ':' + // + cGenre::Genre g = cGenre::GENRE_INVALID; + + if( i->at( i->length()-1 ) == _T(':') ) + { + TSTRING genreStr; + genreStr.assign( i->begin(), i->end()-1 ); + g = cGenreSwitcher::GetInstance()->StringToGenre( genreStr.c_str() ); + + // + // if it is not a valid genre name, then test to see if it could + // be an fconame. If it is not, then it is a badly formed genre. + // + if( g == cGenre::GENRE_INVALID ) + { + std::auto_ptr pParseUtil (iTWFactory::GetInstance()->CreateParserGenreUtil()); + if( ! pParseUtil->IsAbsolutePath( *i ) ) + throw eTWUnknownSectionName( *i ); + } + } + if( g == cGenre::GENRE_INVALID ) + { + // assume that we are in the correct genre; this is a fully qualified object name + // TODO -- throw here if cGenreParserHelper says it isn't a fully qualified name. + // + if( iterGenre != curGenre ) + { + // seek to right list; create it if it is not there... + // + for( curIter = listOut.begin(); curIter != listOut.end(); curIter++ ) + { + if( curIter->first == curGenre ) + break; + } + if( curIter == listOut.end() ) + { + // it doesn't exist; we will have to create a new one. + // + listOut.push_back( GenreObjs() ); + listOut.back().first = curGenre; + curIter = listOut.end() - 1; + } + + iterGenre = curGenre; + } + ASSERT( curIter != listOut.end() ); + // + // add this to the list; assert that it has not been added yet. + // + ObjList::iterator oi; + for( oi = curIter->second.begin(); oi != curIter->second.end(); oi++ ) + { + if( *oi == *i ) + { + //TODO -- what should I do here? probably warn and continue... + ASSERT( false ); + break; + } + } + if( oi == curIter->second.end() ) + curIter->second.push_back( *i ); + } + else + { + // set the current genre to this and continue... + // + curGenre = g; + } + } + +} + + +/////////////////////////////////////////////////////////////////////////////// +// ParseObjectName +/////////////////////////////////////////////////////////////////////////////// +cFCOName cTWUtil::ParseObjectName( const TSTRING& fcoName ) +{ + std::auto_ptr pParseUtil (iTWFactory::GetInstance()->CreateParserGenreUtil()); + cFCOName name( iTWFactory::GetInstance()->GetNameInfo() ); + // + // make sure the fco name is a full path... + // + if( ! pParseUtil->IsAbsolutePath( fcoName ) ) + throw eTWUtilNotFullPath( fcoName ); + // + // construct the list that InterpretFCOName needs.... + std::list inputNameList; + // + // dice up the string into a list + // currently, we only slice it up based on "|" (for nt registry entries) + // + TSTRING::size_type pos = fcoName.find_first_of( _T('|') ); + if( pos != TSTRING::npos ) + { + // if the input string is "foo|bar" then we want the list to + // look like this: "foo", "|", "bar" (three entries) + // + TSTRING str; + str.assign( fcoName, 0, pos ); + inputNameList.push_back( str ); + inputNameList.push_back( _T("|") ); + str.assign( fcoName, pos+1, fcoName.length() - pos ); + inputNameList.push_back( str ); + } + else + { + inputNameList.push_back( fcoName ); + } + + pParseUtil->InterpretFCOName( inputNameList, name ) ; + + return name; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Database and report header helpers +/////////////////////////////////////////////////////////////////////////////// + +TSTRING cTWUtil::GetSystemName() +{ + TSTRING ret; + iFSServices::GetInstance()->GetMachineName(ret); + return ret; +} + +TSTRING cTWUtil::GetIPAddress() +{ + uint32 ipaddress; + if (iFSServices::GetInstance()->GetIPAddress(ipaddress) == false) + return TSS_GetString( cTW, tw::STR_IP_UNKNOWN); + + // convert to host byte-order + ipaddress = tw_ntohl( ipaddress ); + + TOSTRINGSTREAM ret; + ret << (int)(ipaddress >> 24) << _T(".") + << (int)((ipaddress >> 16) & 0xff) << _T(".") + << (int)((ipaddress >> 8) & 0xff) << _T(".") + << (int)(ipaddress & 0xff); + + return ret.str(); +} + +TSTRING cTWUtil::GetCurrentUser() +{ + TSTRING ret; + iFSServices::GetInstance()->GetCurrentUserName(ret); + return ret; +} + +TSTRING cTWUtil::GetHostID() +{ + TSTRING ret; + iFSServices::GetInstance()->GetHostID(ret); + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// PrintErrorMsg +/////////////////////////////////////////////////////////////////////////////// +void cTWUtil::PrintErrorMsg(const eError& e, const TSTRING& strExtra) +{ + ASSERT( e.GetID() != 0 ); // NOTE: BAM 5/9/99 -- there should no longer be an ID of ZERO + + /* BAM 5/9/99 -- this is old stuff + if((e.GetID() == 0) && (e.GetMsg().empty())) + { + // this should only occur at the top level of a program (ie -- twcmdline.cpp) and + // indicates that an error occurred and an error message has already been printed out. + // Therefore, we will do nothing here but return. + return; + } + */ + + cErrorReporter::PrintErrorMsg(e, strExtra); +} + +/////////////////////////////////////////////////////////////////////////////// +// ConfirmYN(const TCHAR* prompt) +// +// prompt the user with given string and wait for a 'Y' or 'N' response. +// returns true if 'Y' entered. +/////////////////////////////////////////////////////////////////////////////// +bool cTWUtil::ConfirmYN(const TCHAR* prompt) +{ + wc16_string reply; + TSTRING s; + int x; + + while (1) + { + TCOUT << prompt; + GetString(reply); + + cStringUtil::Convert(s, reply); + +#ifdef UNICODE + for (x = 0; s[x] && iswctype(s[x], wctype("space") ); x++) + ; +#else + for (x = 0; s[x] && std::isspace( s[x], std::locale() ); x++) + ; +#endif + + if (_totupper(s[x]) == _T('Y')) + return true; + else if (_totupper(s[x]) == _T('N')) + return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// VerifySiteKey +/////////////////////////////////////////////////////////////////////////////// +bool cTWUtil::VerifyCfgSiteKey( const TSTRING& strConfigFile, const TSTRING& siteKeyPath ) +{ + // open the config file + // + cMemoryArchive memArch; + try + { + TSTRING dummyString; + cTWUtil::ReadConfigText( strConfigFile.c_str(), dummyString, &memArch ); + } + catch (eArchive& e) + { + // if the file is corrupted, eArchive may be thrown. + // For sanity sake we need to re-throw this as eTWUtil + TSTRING estr; + estr.assign(TSS_GetString( cCore, core::STR_ERROR_FILENAME )); + estr.append(strConfigFile); + estr.append(TSS_GetString( cCore, core::STR_NEWLINE )); + estr.append(e.GetMsg()); + + throw eTWUtilCorruptedFile( estr ); + } + + // only do the test if there is baggage (indicating the cfg file is encrypted) + // + ASSERT(memArch.Length() >= 0); + if (memArch.Length() <= 0) + return false; + + // get site public key + // + cKeyFile siteKeyfile; + cTWUtil::OpenKeyFile( siteKeyfile, siteKeyPath ); + + // create the two public keys... + // + memArch.Seek( 0, cBidirArchive::BEGINNING ); + cElGamalSigPublicKey pubKey( memArch.GetMemory() ); + + // compare the two .... + // + if( ! pubKey.IsEqual( *siteKeyfile.GetPublicKey() ) ) + { + TSTRING estr; + estr.assign(TSS_GetString( cTW, tw::STR_ERR2_CFG_KEY_MISMATCH1 )); + estr.append(strConfigFile); + estr.append(TSS_GetString( cTW, tw::STR_ERR2_CFG_KEY_MISMATCH2 )); + estr.append(siteKeyPath); + estr.append(TSS_GetString( cTW, tw::STR_ERR2_CFG_KEY_MISMATCH3 )); + + throw eTWUtilCfgKeyMismatch( estr ); + } + + return true; +} + + diff --git a/src/tw/twutil.h b/src/tw/twutil.h new file mode 100644 index 0000000..01c58c2 --- /dev/null +++ b/src/tw/twutil.h @@ -0,0 +1,256 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twutil.h +// +// cTWUtil -- top-level utility functions that can be shared between multiple +// executables + +#ifndef __TWUTIL_H +#define __TWUTIL_H + +#ifndef __TYPES_H +#include "core/types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __WCHAR16_H +#include "core/wchar16.h" +#endif + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +class cFCOReport; +class cElGamalSigPrivateKey; +class cElGamalSigPublicKey; +class cKeyFile; +class cPrivateKeyProxy; +class cFCOSpecList; +class cConfigFile; +class cCmdLineParser; +class cErrorBucket; +class cFileHeaderID; +class eError; +class cFCODbHeader; +class cFCOReportHeader; +class cFCOName; +class cFCODatabaseFile; +class cArchive; +class cMemoryArchive; + +TSS_EXCEPTION( eTWUtil, eError ) +TSS_EXCEPTION( eTWUtilNotFullPath, eTWUtil ) +TSS_EXCEPTION( eTWUtilCfgKeyMismatch, eTWUtil ) +TSS_EXCEPTION( eTWUtilCorruptedFile, eTWUtil ) +TSS_EXCEPTION( eTWUtilBadPassLocal, eTWUtil ) +TSS_EXCEPTION( eTWUtilBadPassSite, eTWUtil ) +TSS_EXCEPTION( eTWUtilEchoModeSet, eTWUtil ) +TSS_EXCEPTION( eTWUtilDbDoesntHaveGenre,eTWUtil ) +TSS_EXCEPTION( eTWUtilPolUnencrypted, eTWUtil ) +TSS_EXCEPTION( eTWUtilObjNotInDb, eTWUtil ) + + +class cTWUtil +{ +public: + //------------------------------------------------------------------------- + // Reading and Writing tripwire file objects (database, report, config + // and policy files). + //------------------------------------------------------------------------- + + static void WriteDatabase(const TCHAR* filename, cFCODatabaseFile& db, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw eError + // writes a database to disk. If an error occurs, a message is spit to stderr and an eError is thrown. + // if bEncrypt is false, then the key pointer may be false, otherwise, it must be non-null + static void ReadDatabase(const TCHAR* filename, cFCODatabaseFile& db, const cElGamalSigPublicKey* pPublicKey, bool& bEncrypted); // throw (eError); + // reads a database from disk. If the db is encrypted, then it will load the named key file into keyFile and + // set bEncrypted to true; otherwise keyFile is not modified and bEncrypted is set to false. + // if keyFile is already open, then the currently loaded keys are used and keyFileName is ignored. + // if an error occurs, this will print the error message to stderr and throw eError. + + static void WriteReport (const TCHAR* filename, const cFCOReportHeader& reportHeader, const cFCOReport& r, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw eError + static void WriteReport (cArchive &archive, const cFCOReportHeader& reportHeader, const cFCOReport& r, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw eError + static void ReadReport (const TCHAR* reportFileName, cFCOReportHeader& reportHeader, cFCOReport& r, const cElGamalSigPublicKey* pPublicKey, bool silent, bool& bEncrypted); // throw eError + static void ReadReport (cArchive &archive, cFCOReportHeader& reportHeader, cFCOReport& r, const cElGamalSigPublicKey* pPublicKey, bool silent, bool& bEncrypted); // throw eError + // same as Read/WriteDatabase above, except it operates on reports + // if an error occurs, this will print the error message to stderr and throw eError. + + static void WriteConfigText(const TCHAR* filename, const TSTRING configText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw (eArchive()) + static void WriteConfigText(cArchive &archive, const TSTRING configText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw (eArchive()) + static void ReadConfigText(const TCHAR* filename, TSTRING& configText, cArchive* pBaggage = 0); + static void ReadConfigText(cArchive &archive, TSTRING& configText, cArchive* pBaggage = 0); + // read and write config file text to and from disk. + // if pBaggage is non-NULL, the contents of the baggage( ie -- the public key ) is copied to the archive. + // eArchive is thrown if filename can not be opened + // eSerializer is thrown if reading or writing fails + // eConfigFile is thrown if config file does not parse correctly during reading + + static void WritePolicyText(const TCHAR* filename, const std::string policyText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); + static void WritePolicyText(cArchive &archive, const std::string policyText, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); + static void ReadPolicyText(const TCHAR* filename, std::string& policyText, const cElGamalSigPublicKey* pPublicKey); + static void ReadPolicyText(cArchive &archive, std::string& policyText, const cElGamalSigPublicKey* pPublicKey); + // read and write policy file to and from disk + // eError() will be thrown on error + + //------------------------------------------------------------------------- + // Higher level manipulation of Tripwire file objects + //------------------------------------------------------------------------- + + static TSTRING GetCfgFilePath(const cCmdLineParser& cmdLine, int cfgFileID); + // Get's the path of the config file, either from the commandline, or from + // the default location. + + static void OpenConfigFile(cConfigFile& cf, cCmdLineParser& cmdLine, int cfgFileID, cErrorBucket& errorBucket, TSTRING& configFileOut ); + // opens the config file, either from a known location or + // from the location specified on the command line. Returns false if it fails + // reads config info into cf + // cfgFileID is the ID of the config file that cCmdLineParser::ArgId() will know about + // if pBaggage is non-NULL, the contents of the baggage( ie -- the public key ) is copied to the archive. + // errors will be reported to errorBucket + // configFileOut returns actual config file used + // returns false on failure + + static void UpdatePolicyFile(const TCHAR* destFileName, const TCHAR* srcFileName, bool bEncrypt, const cElGamalSigPrivateKey* pPrivateKey); // throw eError + // saves the plain text policy file pointed at by srcFileName encrypted with pPrivateKey in destFileName + // if an error occurs an exception suitable for printing with + + //------------------------------------------------------------------------- + // key manipulation utilities + //------------------------------------------------------------------------- + + static bool VerifyCfgSiteKey( const TSTRING& mstrConfigFile, const TSTRING& siteKeyPath ); //throw (eTWUtil) + // This method verifies that either the config file is unencrypted or the public key in the + // config file mstrConfigFile matches the public key contained in the file specified by siteKeyPath. + // Returns true if the keys match or false if the config file is unencrypted. + // Throws eTWUtil if the config file is encrypted but does not match the site key. + // Throws eError if the site keyfile can not be opened. + + static void GetString(wc16_string& ret); + static void GetStringNoEcho(wc16_string& ret); + // This takes an input string from the user with or without displaying it on the screen. + // To use passphrazes compatible between Unicode and non-Unicode, we return the most portable + // type of string, the wide string. + // This simply calls GetString in the scope of a NoEcho object. + + class NoEcho { + public: + NoEcho(); + ~NoEcho(); + }; + // For the lifetime of a cTWUtil::NoEcho object, + // tty echoing on standard input is disabled. + // At construction time, pending input is discarded. + // In order to be friendly to programs like expect, + // whose scripts typically supply input immediately after + // prompting, such prompting should happen after NoEcho + // construction to ensure that such input is not discarded. + + static void OpenKeyFile(cKeyFile& keyFile, TSTRING fileName); // throw (eError) + // this opens the passed in keyfile and associates it with keyFile. + // If an error occurs an exception is thrown with appropriate information. + + enum KeyType { KEY_SITE, KEY_LOCAL, KEY_PROVIDED }; + enum SleepPeriodInSecs{ SLEEP_DEFAULT = 2 }; + static const cElGamalSigPrivateKey* CreatePrivateKey(cKeyFile& keyFile, const WCHAR16* usePassphrase, KeyType keyType, int nSecs = SLEEP_DEFAULT ); + static void CreatePrivateKey(cPrivateKeyProxy& proxy, cKeyFile& keyFile, const WCHAR16* usePassphrase, KeyType keyType, int nSecs = SLEEP_DEFAULT ); + // This will attempt to create the private key from the given key file using the given password. + // If usePassphrase is NULL then the user will be promtped to enter the passphrase. + // If usePassphrase is non-NULL, then it will be used to attempt to opent the private + // key. If this is the wrong password, an error message will be printed and an exception thrown. + // The keyfile must already be open (using OpenKeyFile above). + // The key must be freed using cKeyFile::ReleasePrivateKey(). + // keyType is just used so that an appropriate string can be displayed to the user + // nSecs is the number of to wait before showing user if password was correct. hinders brute + // force (dictionary, etc.) attacks. defaults to 2 seconds. + // NOTE: An eError() exception with an appropriate error message will be thrown on failure. + // TODO: Try to use the second version as we will want to upgrade to this some day - dmb + + //------------------------------------------------------------------------- + // Command Line + //------------------------------------------------------------------------- + + typedef std::vector ObjList; + typedef std::pair GenreObjs; + typedef std::vector GenreObjList; + static void ParseObjectList( GenreObjList& listOut, const ObjList& listIn ); // throw eError() + // takes a list of strings (listIn) and turns them into a collection of pairs. + // This is used while integrity checking or printing a set of FCOs. This takes the form: [genre|objName]+ + // where each object is associated with the most recently mentioned genre. If an object appears + // before any genre identifiers, it is assumed to be in FS on unix or NTFS on NT. + // eError will be thrown if an unknown genre is encountered + static cFCOName ParseObjectName( const TSTRING& fcoName ); // throw (eError) + // converts a string representation of an FCO name (that was passed in on the command line for integrity + // check or database printing) into a cFCOName. It is assumed that the name is for an object in the current + // genre. If the string cannot be converted (ie -- relative path or invalid formatting), eError is thrown. + + //------------------------------------------------------------------------- + // Database and report header helpers + //------------------------------------------------------------------------- + + // These are all used for filling out HeaderInfo structures + static TSTRING GetSystemName(); + static TSTRING GetIPAddress(); + static TSTRING GetCurrentUser(); + static TSTRING GetHostID(); + + //------------------------------------------------------------------------- + // Micellaneous + //------------------------------------------------------------------------- + + static bool IsObjectEncrypted( const TCHAR* objFileName, const cFileHeaderID& fhid, const TSTRING& errorMsg ); + static bool IsObjectEncrypted( cArchive &arch, const cFileHeaderID& fhid, const TSTRING& errorMsg ); + // Tests an object serialized to objFileName to see if it's encrypted. fhid ensures that the object in the + // file is of the correct type. + // If an error occurs while reading the file, this WILL PRINT an error message errorMsg, + // then it will throw eError(NULL). + + static void PrintErrorMsg(const eError& e, const TSTRING& strExtra = _T("")); + // nicely displays the contents of the exception to stderr. + // currently, it has the format: + // ### Error e.GetErrorNum(): e.GetMsg() : cErrorTable::GetErrorString(e.GetErrorNum()) + + static bool ConfirmYN(const TCHAR* prompt); + // prompt the user with given string and wait for a 'Y' or 'N' response. + // returns true if 'Y' entered. +}; + + +#endif //__TWUTIL_H + diff --git a/src/tw/twutil_t.cpp b/src/tw/twutil_t.cpp new file mode 100644 index 0000000..625f9b3 --- /dev/null +++ b/src/tw/twutil_t.cpp @@ -0,0 +1,138 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twutil_t.cpp + +#include "stdtw.h" +#include "twutil.h" +#include "test/test.h" +#include + + + +#if IS_UNIX +//#include +#include +#include +#endif + +std::string WideToNarrow( const TSTRING& strWide ); + +void TestTWUtil() +{ +#pragma message( __FILE__ "(1) : TODO - implement this test file") +#if 0 + // TODO: we should test more than the file exists stuff, but that + // is all I need to do for right now. + cDebug d("TestTWUtil"); + + ///////////////////////////////////////////////////////////////// + // Test FileExists() and FileWritable() + + d.TraceAlways("Testing FileExists() and FileWritable()\n"); + + // assuming the current dir is writable, this test should succeed + TEST(cTWUtil::FileWritable(_T("afilethatdoesnotexist.tmp")) == true); + + TSTRING tmpDir = TEMP_DIR; + tmpDir += _T("/fileexistdir"); + TSTRING tmpFN = tmpDir; + tmpFN += _T("/fileexiststest.tmp"); + + // make a subdir in the TEMP_DIR + #if IS_UNIX + _tmkdir(tmpDir.c_str(), 0700); + #else + _tmkdir(tmpDir.c_str()); + #endif + + _tchmod(tmpDir.c_str(), 0700); + + // make sure file is not there + _tchmod(tmpFN.c_str(), 0777); + _tunlink(tmpFN.c_str()); + + // make sure exists tests false, writable is true + // and checking writable should not create the file + TEST(cTWUtil::FileExists(tmpFN) == false); + TEST(cTWUtil::FileWritable(tmpFN) == true) + TEST(cTWUtil::FileExists(tmpFN) == false); + + // make the dir read only and make sure write tests false + #if IS_UNIX // windows fails this test, perhaps because I am an administrator? + _tchmod(tmpDir.c_str(), 0500); + TEST(cTWUtil::FileWritable(tmpFN) == false); + _tchmod(tmpDir.c_str(), 0700); + #endif + + // create the file + { + std::ofstream ostr(WideToNarrow(tmpFN).c_str()); + ostr << "Hey there.\n"; + } + + // test a read only file + _tchmod(tmpFN.c_str(), 0400); + TEST(cTWUtil::FileWritable(tmpFN) == false); + + // test a writable file + _tchmod(tmpFN.c_str(), 0666); + TEST(cTWUtil::FileWritable(tmpFN) == true); + + // delete the test file and dir + _tunlink(tmpFN.c_str()); + _tunlink(tmpDir.c_str()); +#endif +} + +std::string WideToNarrow( const TSTRING& strWide ) +{ +#ifdef _UNICODE + std::string strA; + for( TSTRING::const_iterator i = strWide.begin(); i != strWide.end(); i++ ) + { + char ach[4]; + ASSERT( MB_CUR_MAX <= 4 ); + + int n = wctomb( ach, *i ); + ASSERT( n != -1 ); + + for( int j = 0; j < n; j++ ) + strA += ach[j]; + } + + return strA; +#else + return strWide; +#endif +} + diff --git a/src/twadmin/Makefile.am b/src/twadmin/Makefile.am new file mode 100644 index 0000000..1a4394b --- /dev/null +++ b/src/twadmin/Makefile.am @@ -0,0 +1,17 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 + +INCLUDES = -I.. +LIBS = -ltripwire -lcryptlib @LIBS@ +LDFLAGS = @LDFLAGS@ -L../../lib + +sbin_PROGRAMS = twadmin +twadmin_SOURCES = \ + keygeneration.cpp stdtwadmin.cpp twadmin.cpp twadmincl.cpp \ + twadminerrors.cpp twadminmain.cpp twadminstrings.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +CLEANFILES = ../../bin/twadmin + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin diff --git a/src/twadmin/Makefile.in b/src/twadmin/Makefile.in new file mode 100644 index 0000000..4f70476 --- /dev/null +++ b/src/twadmin/Makefile.in @@ -0,0 +1,423 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(twadmin_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +sbin_PROGRAMS = twadmin$(EXEEXT) +subdir = src/twadmin +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(sbin_PROGRAMS) +am_twadmin_OBJECTS = keygeneration.$(OBJEXT) stdtwadmin.$(OBJEXT) \ + twadmin.$(OBJEXT) twadmincl.$(OBJEXT) twadminerrors.$(OBJEXT) \ + twadminmain.$(OBJEXT) twadminstrings.$(OBJEXT) +twadmin_OBJECTS = $(am_twadmin_OBJECTS) +twadmin_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(twadmin_SOURCES) +DIST_SOURCES = $(twadmin_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ -L../../lib +LIBOBJS = @LIBOBJS@ +LIBS = -ltripwire -lcryptlib @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 +INCLUDES = -I.. +twadmin_SOURCES = \ + keygeneration.cpp stdtwadmin.cpp twadmin.cpp twadmincl.cpp \ + twadminerrors.cpp twadminmain.cpp twadminstrings.cpp + +CLEANFILES = ../../bin/twadmin +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/twadmin/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/twadmin/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$f"; \ + done + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +twadmin$(EXEEXT): $(twadmin_OBJECTS) $(twadmin_DEPENDENCIES) + @rm -f twadmin$(EXEEXT) + $(CXXLINK) $(twadmin_LDFLAGS) $(twadmin_OBJECTS) $(twadmin_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-sbinPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am uninstall-sbinPROGRAMS + + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/twadmin/keygeneration.cpp b/src/twadmin/keygeneration.cpp new file mode 100644 index 0000000..5edb2a8 --- /dev/null +++ b/src/twadmin/keygeneration.cpp @@ -0,0 +1,209 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// keygeneration.cpp +// + +#include "stdtwadmin.h" + +#include "keygeneration.h" +#include "twcrypto/crypto.h" +#include "twcrypto/keyfile.h" +#include "core/error.h" +#include "twadminstrings.h" +#include "core/usernotify.h" + + +#ifndef _DEBUG +const cElGamalSig::KeySize TRIPWIRE_PUBLIC_KEYSIZE = cElGamalSig::KEY1024; +#else +const cElGamalSig::KeySize TRIPWIRE_PUBLIC_KEYSIZE = cElGamalSig::KEY1024; +#endif + +struct tGK +{ + bool doneFlag; + int retValue; + int8* passphrase; + int passphraseLen; + const TCHAR* keyPath; + + enum ReturnValue + { + OK = 0, + INVALIDPARAM = 1, + GENERATION_ERROR = 2, + FILE_WRITE_ERROR = 3, + LAST + }; + + tGK() + { + doneFlag = false; + retValue = 0; + passphrase = 0; + passphraseLen = 0; + keyPath = 0; + } +}; + +static void GeneratePublicPrivateKeys(void* pParams) +{ + tGK* pGK = (tGK*)pParams; + + if (pGK->doneFlag != false || + pGK->keyPath == 0 || + _tcslen(pGK->keyPath) == 0) + { + pGK->retValue = tGK::INVALIDPARAM; + pGK->doneFlag = true; + return; + } + + try { + cKeyFile keyfile; + +#ifdef _DEBUG + cDebug d("GeneratePublicPrivateKeys"); + d.TraceDebug("calling keyfile.GenerateKeys()\n"); +#endif + + try + { + keyfile.GenerateKeys(TRIPWIRE_PUBLIC_KEYSIZE, pGK->passphrase, pGK->passphraseLen); + } + catch(eKeyFile&) + { + pGK->retValue = tGK::GENERATION_ERROR; + pGK->doneFlag = true; + return; + } + +#ifdef _DEBUG + d.TraceDebug(_T("writing to keyfile %s\n"), pGK->keyPath); +#endif + + try + { + keyfile.WriteFile(pGK->keyPath); + } + catch(eKeyFile&) + { + pGK->retValue = tGK::FILE_WRITE_ERROR; + pGK->doneFlag = true; + return; + } + } + catch(eError& e) + { + (void)e; + pGK->retValue = tGK::GENERATION_ERROR; + pGK->doneFlag = true; + return; + } + + pGK->retValue = tGK::OK; + pGK->doneFlag = true; + return; +} + +bool GenerateKey(const TCHAR* keyPath, wc16_string passphrase) +{ +#ifndef WORDS_BIGENDIAN + passphrase.swapbytes(); +#endif + +#ifdef _DEBUG + // test reading in the keys + wc16_string passphrase_copy = passphrase.c_str(); + wc16_string passphrase_copy2 = passphrase.c_str(); +#endif + + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_GENERATING_KEYS).c_str()); + +#if IS_UNIX + fflush(stdout); +#endif + + tGK gk; + gk.passphrase = (int8*)passphrase.data(); + gk.passphraseLen = passphrase.length() * sizeof(WCHAR16); + gk.keyPath = keyPath; + +#if IS_UNIX + GeneratePublicPrivateKeys(&gk); +#endif + + if (gk.retValue != tGK::OK) + { + switch (gk.retValue) + { + case tGK::FILE_WRITE_ERROR: + TCERR << std::endl << TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYGEN_FILEWRITE) << gk.keyPath << std::endl; + default: + TCERR << std::endl << TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYGEN) << gk.keyPath + << TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYGEN2) << std::endl; + break; + } + + return false; + } + +#ifdef _DEBUG + // test reading in the keys + cKeyFile keyfile; + + keyfile.ReadFile(keyPath); + + ASSERT(keyfile.GetPrivateKey((int8*)passphrase_copy.data(), passphrase_copy.length() * sizeof(WCHAR16)) != 0); + keyfile.ReleasePrivateKey(); + + //keyfile.WriteFile(_T("tripwire2.key")); + + // test memory writing + int8 mem[4000]; + ASSERT(4000 > keyfile.GetWriteLen()); + + keyfile.WriteMem(mem); + + cKeyFile k2; + k2.ReadMem(mem); + + k2.GetPrivateKey((int8*)passphrase_copy2.data(), passphrase_copy2.length() * sizeof(WCHAR16)); + k2.ReleasePrivateKey(); +#endif + + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_GENERATION_COMPLETE).c_str()); + + return true; +} + diff --git a/src/twadmin/keygeneration.h b/src/twadmin/keygeneration.h new file mode 100644 index 0000000..d2fe8fc --- /dev/null +++ b/src/twadmin/keygeneration.h @@ -0,0 +1,50 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// keygeneration.h +// + +#ifndef __KEYGENERATION_H +#define __KEYGENERATION_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __WCHAR16_H +#include "core/wchar16.h" +#endif + +bool GenerateKey(const TCHAR* keyPath, wc16_string passphrase); + +#endif + diff --git a/src/twadmin/resource.h b/src/twadmin/resource.h new file mode 100644 index 0000000..5510e67 --- /dev/null +++ b/src/twadmin/resource.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script2.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + diff --git a/src/twadmin/stdtwadmin.cpp b/src/twadmin/stdtwadmin.cpp new file mode 100644 index 0000000..380ac77 --- /dev/null +++ b/src/twadmin/stdtwadmin.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdadmin.cpp +// Date....: 5/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwadmin.h" + +// eof: stdtwadmin.cpp diff --git a/src/twadmin/stdtwadmin.h b/src/twadmin/stdtwadmin.h new file mode 100644 index 0000000..8d7c961 --- /dev/null +++ b/src/twadmin/stdtwadmin.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtwadmin.h +// +// Standard includes for twadmin +// + +#include "core/stdcore.h" + diff --git a/src/twadmin/twadmin.cpp b/src/twadmin/twadmin.cpp new file mode 100644 index 0000000..e49e8ee --- /dev/null +++ b/src/twadmin/twadmin.cpp @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twadmin.cpp +// Date....: 05/11/99 +// Creator.: bmcfeely +// +// + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Includes +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "stdtwadmin.h" +#include "twadmin.h" +#include "tw/tw.h" // for cTW +#include "twadminerrors.h" + + +TSS_ImplementPackage( cTWAdmin ) + +//============================================================================= +// cTWAdmin::cTWAdmin() +//----------------------------------------------------------------------------- +// REQUIRES: +// +// EFFECTS: +// +// POSTCONDITIONS: +// +// COMPLEXITY: +// Constant +// +cTWAdmin::cTWAdmin() +{ + // + // set up dependencies + // + TSS_Dependency( cTW ); + TSS_REGISTER_PKG_ERRORS ( twadmin ); +} + +// eof: twadmin.cpp diff --git a/src/twadmin/twadmin.h b/src/twadmin/twadmin.h new file mode 100644 index 0000000..b780e2f --- /dev/null +++ b/src/twadmin/twadmin.h @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twadmin.h +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// +// The Package class for the TSS twadmin executable. +// + +#ifndef __TWADMIN_H +#define __TWADMIN_H + +//--Requirements + +#include "core/package.h" // for: Packaging Abstraction + +//--Classes + +TSS_BeginPackage( cTWAdmin ) + + TSS_DECLARE_STRINGTABLE; + +public: + cTWAdmin(); + +TSS_EndPackage( cTWAdmin ) + +#endif //#ifndef __TWADMIN_H + diff --git a/src/twadmin/twadmincl.cpp b/src/twadmin/twadmincl.cpp new file mode 100644 index 0000000..5821487 --- /dev/null +++ b/src/twadmin/twadmincl.cpp @@ -0,0 +1,2678 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twadmincl.cpp -- command line parsing for twadmin +// + +#include "stdtwadmin.h" + +#include "twadmincl.h" +#include "twadminstrings.h" +#include "keygeneration.h" +#include "core/errorgeneral.h" +#include "core/errorbucketimpl.h" // needed for the error table +#include "core/archive.h" +#include "core/usernotify.h" +#include "core/cmdlineparser.h" +#include "core/usernotify.h" +#include "fco/fconame.h" +#include "tw/configfile.h" +#include "tw/twutil.h" +#include "tw/filemanipulator.h" +#include "tw/fcodatabasefile.h" +#include "tw/fcoreport.h" +#include "tw/policyfile.h" +#include "tw/systeminfo.h" +#include "tw/twerrors.h" +#include "tw/twstrings.h" +#include "twparser/policyparser.h" +#include "twcrypto/keyfile.h" +#include "core/stringutil.h" +#include "util/fileutil.h" +#include "twcrypto/crypto.h" +#include "core/displayencoder.h" + +// forwards +static bool NotifyFileType(const cFileHeaderID& id, uint32 version, iUserNotify::VerboseLevel vl); + // Calls UserNotify(V_VERBOSE, ...) to print out type of file specified in cFileHeaderID. + // Returns false if cFileHeaderID not recognized. + // Used in changing and removing encryption algorithms +static bool NotifyEncryptionType(cFileHeader::Encoding encoding, iUserNotify::VerboseLevel vl); + // Calls UserNotify(V_VERBOSE, ...) to print out type of file specified in cFileHeaderID. + // Returns false if encoding not recognized. + // Used in changing and removing encryption algorithms + + +// error implementations + +eTWACreateCfgMissingSitekey::eTWACreateCfgMissingSitekey( const TSTRING& msg, uint32 flags ) + : eTWA( TSTRING(), flags ) +{ + mMsg = TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CREATE_CFG_MISSING_KEYFILE) + msg; +} + +eTWACreateCfgSitekeyMismatch::eTWACreateCfgSitekeyMismatch( const TSTRING& specifiedKeyfile, const TSTRING& configKeyfile, uint32 flags ) + : eTWA( TSTRING(), flags ) +{ + mMsg = TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH1); + mMsg.append(specifiedKeyfile); + mMsg.append(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH2)); + mMsg.append(configKeyfile); + mMsg.append(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH3)); +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeCommon -- common modes that all iTWAMode implementations will +// derive from. + +class cTWAModeCommon : public iTWAMode +{ +protected: + int mVerbosity; // must be 0 <= n <= 2 + TSTRING mPolFile; + TSTRING mSiteKeyFile; + bool mSiteKeyFileProvieded; + TSTRING mLocalKeyFile; + bool mLocalKeyFileProvieded; + bool mLatePassphrase; + + cTWAModeCommon() : mVerbosity(1), mSiteKeyFileProvieded(false), mLocalKeyFileProvieded(false), mLatePassphrase(false) {} + + void InitCmdLineCommon(cCmdLineParser& parser); + void FillOutConfigInfo(const cConfigFile* cf); + void FillOutCmdLineInfo(const cCmdLineParser& parser); +}; + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineCommon -- initializes the command line switches common to all +// modes + +void cTWAModeCommon::InitCmdLineCommon(cCmdLineParser& parser) +{ + parser.AddArg(cTWAdminCmdLine::HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::VERBOSE, TSTRING(_T("v")), TSTRING(_T("verbose")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SILENT, TSTRING(_T("s")), TSTRING(_T("silent")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SILENT, TSTRING(_T("")), TSTRING(_T("quiet")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::CFG_FILE, TSTRING(_T("c")), TSTRING(_T("cfgfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::POL_FILE, TSTRING(_T("p")), TSTRING(_T("polfile")), cCmdLineParser::PARAM_ONE); + parser.AddMutEx(cTWAdminCmdLine::VERBOSE, cTWAdminCmdLine::SILENT); +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutConfigInfo -- fills out all the common info with config file information +/////////////////////////////////////////////////////////////////////////////// +void cTWAModeCommon::FillOutConfigInfo(const cConfigFile* cf) +{ + if (cf == 0) + return; + + TSTRING str; + if(cf->Lookup(TSTRING(_T("POLFILE")), str)) + mPolFile = str; + if(cf->Lookup(TSTRING(_T("SITEKEYFILE")), str)) + mSiteKeyFile = str; + if(cf->Lookup(TSTRING(_T("LOCALKEYFILE")), str)) + mLocalKeyFile = str; + if(cf->Lookup(TSTRING(_T("LATEPROMPTING")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + mLatePassphrase = true; + } + + // + // turn all of the file names into full paths (they're relative to the exe dir) + // + TSTRING fullPath; + if(!mPolFile.empty() && iFSServices::GetInstance()->FullPath( fullPath, mPolFile, cSystemInfo::GetExeDir() )) + mPolFile = fullPath; + if(!mSiteKeyFile.empty() && iFSServices::GetInstance()->FullPath( fullPath, mSiteKeyFile, cSystemInfo::GetExeDir() )) + mSiteKeyFile = fullPath; + if(!mLocalKeyFile.empty() && iFSServices::GetInstance()->FullPath( fullPath, mLocalKeyFile, cSystemInfo::GetExeDir() )) + mLocalKeyFile = fullPath; +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutCmdLineInfo -- fills out info common to all modes that appears on the +// command line. +/////////////////////////////////////////////////////////////////////////////// +void cTWAModeCommon::FillOutCmdLineInfo(const cCmdLineParser& parser) +{ + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::VERBOSE: + mVerbosity = 2; + break; + case cTWAdminCmdLine::SILENT: + mVerbosity = 0; + break; + case cTWAdminCmdLine::POL_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mPolFile = iter.ParamAt(0); + break; + case cTWAdminCmdLine::SITE_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mSiteKeyFile = iter.ParamAt(0); + mSiteKeyFileProvieded = true; + break; + case cTWAdminCmdLine::LOCAL_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mLocalKeyFile = iter.ParamAt(0); + mLocalKeyFileProvieded = true; + break; + } + } + + // Turn all of the file names into full paths for nice presentation to the user. + // Note: We depend later on the if one of these files is not specified, the string + // is empty. Currently FullPath() expands "" to the CWD. + TSTRING fullPath; + if(!mPolFile.empty() && iFSServices::GetInstance()->FullPath(fullPath, mPolFile)) + mPolFile = fullPath; + if(!mSiteKeyFile.empty() && iFSServices::GetInstance()->FullPath(fullPath, mSiteKeyFile)) + mSiteKeyFile = fullPath; + if(!mLocalKeyFile.empty() && iFSServices::GetInstance()->FullPath(fullPath, mLocalKeyFile)) + mLocalKeyFile = fullPath; + + // use the verbosity information + ASSERT((mVerbosity >= 0) && (mVerbosity < 3)); + iUserNotify::GetInstance()->SetVerboseLevel(mVerbosity); +} + +/////////////////////////////////////////////////////////////////////////////// +// TWAdmin modes +// +// No one else should need to see these classes, so we will keep them +// localized to this file. +// + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeCreateCfg + +class cTWAModeCreateCfg : public cTWAModeCommon +{ +public: + cTWAModeCreateCfg(); + virtual ~cTWAModeCreateCfg(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_CFGFILE ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_CREATE_CONFIG; } + +private: + TSTRING mPlaintextConfig; + TSTRING mEncryptedConfig; + wc16_string mPassPhrase; // pass phrase for private key + bool mPassPhraseProvided; + bool mNoEncryption; +}; + +cTWAModeCreateCfg::cTWAModeCreateCfg() +{ + mNoEncryption = false; + mPassPhraseProvided = false; +} + +cTWAModeCreateCfg::~cTWAModeCreateCfg() +{ +} + +void cTWAModeCreateCfg::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_CREATE_CONFIG, TSTRING(_T("")), TSTRING(_T("create-cfgfile")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::PASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::NO_ENCRYPTION, TSTRING(_T("e")), TSTRING(_T("no-encryption")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + parser.AddMutEx(cTWAdminCmdLine::NO_ENCRYPTION, cTWAdminCmdLine::SITE_KEY_FILE); + parser.AddMutEx(cTWAdminCmdLine::NO_ENCRYPTION, cTWAdminCmdLine::PASSPHRASE); +} + +bool cTWAModeCreateCfg::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + TSTRING str; + + FillOutConfigInfo(cf); + + FillOutCmdLineInfo(parser); + + bool fConfigOnCmdLine = false; + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::NO_ENCRYPTION: + mNoEncryption = true; + break; + case cTWAdminCmdLine::PASSPHRASE: + { + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mPassPhrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mPassPhraseProvided = true; + } + break; + case cTWAdminCmdLine::CFG_FILE: + if (iter.NumParams() < 1) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_CONFIG))); + return false; + } + mEncryptedConfig = iter.ParamAt(0); + fConfigOnCmdLine = true; + break; + case cTWAdminCmdLine::PARAMS: + ASSERT(iter.NumParams() == 1); + mPlaintextConfig = iter.ParamAt(0); + + break; + } + } + + // get full path to files + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, mPlaintextConfig ) ) + mPlaintextConfig = strFullPath; + + // OK, now we need to figure out where to put the new config file. + // If the location was specified on the command line, get the full path to it. + // otherwise, the location is the dir that this exe is in. + if( fConfigOnCmdLine ) + { + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, mEncryptedConfig ) ) + mEncryptedConfig = strFullPath; + } + else + { + iFSServices::GetInstance()->FullPath( mEncryptedConfig, TSS_GetString(cTW, tw::STR_DEF_CFG_FILENAME ), + cSystemInfo::GetExeDir() ) ; + } + + return true; +} + +int cTWAModeCreateCfg::Execute(cErrorQueue* pQueue) +{ + if (mPlaintextConfig.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_PT_CONFIG))); + return 1; + } + + if (mEncryptedConfig.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_CONFIG))); + return 1; + } + + if (mSiteKeyFile.empty() && !mNoEncryption) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_SITE_KEY_NOENCRYPT_NOT_SPECIFIED))); + return 1; + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_UPCONFIG_VERBOSE_PT_CONFIG).c_str(), + cDisplayEncoder::EncodeInline( mPlaintextConfig ).c_str()); + + + cFileArchive arch; + arch.OpenRead(mPlaintextConfig.c_str(), cFileArchive::FA_OPEN_TEXT); // Note: eArchive may be thrown + + // read in config text + std::string narrowPlaintext; + narrowPlaintext.resize(arch.Length()); + // NOTE: archive may write fewer than arch.Length() bytes since + // it is converting CR/LF to CR. + int cbRead = arch.ReadBlob((void*)narrowPlaintext.data(), arch.Length()); + narrowPlaintext.resize( cbRead ); // may have garbage after plaintext[cbRead] due to text mode conversion + + TSTRING plaintext = cStringUtil::StrToTstr(narrowPlaintext); + + // Try reading it to see if there are any problems. + // Also open the keyfile so we can verify the keyfile specified in the plaintext + // matches the key we intend to encrypt the config file with. + cKeyFile plaintextKeyFile; + TSTRING plaintextKeyFileName; + bool plaintextKeyFileLoaded = false; + try + { + cConfigFile cf; + cf.ReadString(plaintext); + + if ( (plaintextKeyFileLoaded = cf.Lookup(_T("SITEKEYFILE"), plaintextKeyFileName)) == true && + (plaintextKeyFileLoaded = !plaintextKeyFileName.empty()) == true + ) + { + TSTRING fullPath; + if (iFSServices::GetInstance()->FullPath( fullPath, plaintextKeyFileName, cSystemInfo::GetExeDir() )) + plaintextKeyFileName = fullPath; + + cTWUtil::OpenKeyFile(plaintextKeyFile, plaintextKeyFileName); + plaintextKeyFileLoaded = true; + } + } + catch (eConfigFile& e) + { + pQueue->AddError( e ); + return 1; + } + + cKeyFile specifiedKeyFile; + const cElGamalSigPrivateKey* pPrivateKey; + + if (!mNoEncryption) + { + cTWUtil::OpenKeyFile(specifiedKeyFile, mSiteKeyFile); + if (!plaintextKeyFileLoaded) + { + // User wishes to create a config file using a key, but has not specified the key in the config file. + // For safty and sanity reasons we do not let them do this. + pQueue->AddError( eTWACreateCfgMissingSitekey(TSTRING()) ); + return false; + } + else if (!specifiedKeyFile.GetPublicKey()->IsEqual(*plaintextKeyFile.GetPublicKey())) + { + // The site key specified in this config file does not match the sitekey they are encrypting the + // config file with. This is likely to lead to problems so we try to catch it here. + pQueue->AddError( eTWACreateCfgSitekeyMismatch(mSiteKeyFile, plaintextKeyFileName) ); + return false; + } + + pPrivateKey = cTWUtil::CreatePrivateKey(specifiedKeyFile, mPassPhraseProvided ? mPassPhrase.c_str() : NULL, cTWUtil::KEY_SITE); + } + else + pPrivateKey = 0; + + // Make sure we can create the file + cFileUtil::TestFileWritable(mEncryptedConfig); + + // backup current file if it exists + cFileUtil::BackupFile(mEncryptedConfig); + + if (!mNoEncryption) + { + cTWUtil::WriteConfigText(mEncryptedConfig.c_str(), plaintext, true, pPrivateKey); + specifiedKeyFile.ReleasePrivateKey(); + } + else + cTWUtil::WriteConfigText(mEncryptedConfig.c_str(), plaintext, false, 0); + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeCreatePol + +class cTWAModeCreatePol : public cTWAModeCommon +{ +public: + cTWAModeCreatePol(); + virtual ~cTWAModeCreatePol(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_POLFILE ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_CREATE_POLICY; } + +private: + TSTRING mPlaintextPolicy; + wc16_string mPassPhrase; // pass phrase for private key + bool mPassPhraseProvided; + bool mNoEncryption; +}; + +cTWAModeCreatePol::cTWAModeCreatePol() +{ + mNoEncryption = false; + mPassPhraseProvided = false; +} + +cTWAModeCreatePol::~cTWAModeCreatePol() +{ +} + +void cTWAModeCreatePol::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_CREATE_POLICY, TSTRING(_T("")), TSTRING(_T("create-polfile")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::PASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::NO_ENCRYPTION, TSTRING(_T("e")), TSTRING(_T("no-encryption")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + parser.AddMutEx(cTWAdminCmdLine::NO_ENCRYPTION, cTWAdminCmdLine::SITE_KEY_FILE); + parser.AddMutEx(cTWAdminCmdLine::NO_ENCRYPTION, cTWAdminCmdLine::PASSPHRASE); +} + +bool cTWAModeCreatePol::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + TSTRING str; + + FillOutConfigInfo(cf); + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::NO_ENCRYPTION: + mNoEncryption = true; + break; + case cTWAdminCmdLine::PASSPHRASE: + { + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mPassPhrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mPassPhraseProvided = true; + } + break; + case cTWAdminCmdLine::PARAMS: + ASSERT(iter.NumParams() == 1); + mPlaintextPolicy = iter.ParamAt(0); + break; + } + } + + // get full path to files + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, mSiteKeyFile ) ) + mSiteKeyFile = strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, mPlaintextPolicy ) ) + mPlaintextPolicy = strFullPath; + + if (mPlaintextPolicy.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_PT_POLICY))); + return false; + } + + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +int cTWAModeCreatePol::Execute(cErrorQueue* pQueue) +{ + if (mPlaintextPolicy.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_PT_POLICY))); + return 1; + } + + if (mPolFile.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_POLICY))); + return 1; + } + + if (mSiteKeyFile.empty() && !mNoEncryption) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_SITE_KEY_NOENCRYPT_NOT_SPECIFIED))); + return 1; + } + + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_UPCONFIG_VERBOSE_PT_POLICY).c_str(), + cDisplayEncoder::EncodeInline( mPlaintextPolicy ).c_str()); + + // open policy file as text + cFileArchive arch; + arch.OpenRead(mPlaintextPolicy.c_str(), cFileArchive::FA_OPEN_TEXT); // Note: eArchive may be thrown + + // read in policy text + std::string plaintext; + plaintext.resize(arch.Length()); + // NOTE: archive may write fewer than arch.Length() bytes since + // it is converting CR/LF to CR. + int cbRead = arch.ReadBlob((void*)plaintext.data(), arch.Length()); + plaintext.resize( cbRead ); // may have garbage after plaintext[cbRead] due to text mode conversion + + // + // make sure the policy file parses correctly before we update the old one + // + std::istringstream in( plaintext ); + cPolicyParser parser( in ); + try + { + parser.Check( pQueue ); + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, + TSS_GetString(cTWAdmin, twadmin::STR_POL_NOT_UPDATED).c_str() ); + return 1; + } + + // + // open the key file... + // + cKeyFile keyfile; + + const cElGamalSigPrivateKey* pPrivateKey; + + if (!mNoEncryption) + { + cTWUtil::OpenKeyFile(keyfile, mSiteKeyFile); + pPrivateKey = cTWUtil::CreatePrivateKey(keyfile, mPassPhraseProvided ? mPassPhrase.c_str() : NULL, cTWUtil::KEY_SITE); + } + else + pPrivateKey = 0; + + // Make sure we can create the file + cFileUtil::TestFileWritable(mPolFile); + + // backup current file if it exists + cFileUtil::BackupFile(mPolFile); + + if (!mNoEncryption) + { + cTWUtil::WritePolicyText(mPolFile.c_str(), plaintext, true, pPrivateKey); + keyfile.ReleasePrivateKey(); + } + else + cTWUtil::WritePolicyText(mPolFile.c_str(), plaintext, false, 0); + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModePrintCfg + +class cTWAModePrintCfg : public cTWAModeCommon +{ +public: + cTWAModePrintCfg(); + virtual ~cTWAModePrintCfg(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_CFGFILE ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_PRINT_CONFIG; } + +private: + TSTRING mEncryptedConfig; +}; + +cTWAModePrintCfg::cTWAModePrintCfg() +{ +} + +cTWAModePrintCfg::~cTWAModePrintCfg() +{ +} + +void cTWAModePrintCfg::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_PRINT_CONFIG, TSTRING(_T("")), TSTRING(_T("print-cfgfile")), cCmdLineParser::PARAM_NONE); +} + +bool cTWAModePrintCfg::Init(const cConfigFile* cf, const cCmdLineParser& parser) //throw(eTWUTil) +{ + FillOutConfigInfo(cf); + FillOutCmdLineInfo(parser); + + mEncryptedConfig = cTWUtil::GetCfgFilePath(parser, cTWAdminCmdLine::CFG_FILE); + + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +int cTWAModePrintCfg::Execute(cErrorQueue* pQueue) +{ + try + { + TSTRING configText; + cTWUtil::ReadConfigText(mEncryptedConfig.c_str(), configText); + + // Note: I believe print config and print policy are the only time we should + // print to standard out directly. + TCOUT << cDisplayEncoder::EncodeInlineAllowWS( configText ); + TCOUT << std::endl; + } + catch (eError& e) + { + TSTRING extra; + extra += TSS_GetString(cTW, tw::STR_NEWLINE); + extra += TSS_GetString(cTW, tw::STR_ERR_TWCFG_CANT_READ); + cTWUtil::PrintErrorMsg(e, extra); + return 1; + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModePrintPol + +class cTWAModePrintPol : public cTWAModeCommon +{ +public: + cTWAModePrintPol(); + virtual ~cTWAModePrintPol(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_POLFILE ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_PRINT_POLICY; } +private: +}; + +cTWAModePrintPol::cTWAModePrintPol() +{ +} + +cTWAModePrintPol::~cTWAModePrintPol() +{ +} + +void cTWAModePrintPol::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_PRINT_POLICY, TSTRING(_T("")), TSTRING(_T("print-polfile")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); +} + +bool cTWAModePrintPol::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + FillOutConfigInfo(cf); + FillOutCmdLineInfo(parser); + + return true; +} + +int cTWAModePrintPol::Execute(cErrorQueue* pQueue) +{ + try + { + cKeyFile sitekey; + + bool policyEncrypted = cTWUtil::IsObjectEncrypted(mPolFile.c_str(), cPolicyFile::GetFileHeaderID(), TSS_GetString( cTWAdmin, twadmin::STR_ERR2_UNABLE_TO_PRINT_POLICY ) ); + + if (policyEncrypted) + { + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + cTWUtil::OpenKeyFile(sitekey, mSiteKeyFile); + } + else + cTWUtil::PrintErrorMsg(eTWUtilPolUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + + std::string policyText; + + iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"), + TSS_GetString(cTW, tw::STR_OPEN_POLICY_FILE).c_str(), + cDisplayEncoder::EncodeInline( mPolFile ).c_str()); + + cTWUtil::ReadPolicyText(mPolFile.c_str(), policyText, policyEncrypted ? sitekey.GetPublicKey() : 0); + + // Note: I believe print config and print policy are the only time we should + // print to standard out directly. + TCOUT << cDisplayEncoder::EncodeInlineAllowWS( cStringUtil::StrToTstr( policyText ) ); + TCOUT << std::endl; + } + catch (eError& e) + { + cTWUtil::PrintErrorMsg(e); + return 1; + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeRemoveEncryption + +class cTWAModeRemoveEncryption : public cTWAModeCommon +{ +public: + cTWAModeRemoveEncryption(); + virtual ~cTWAModeRemoveEncryption(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage () { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_REMOVE_ENCRYPTION ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION; } +private: + std::list mFileList; + wc16_string mSitePassphrase; + wc16_string mLocalPassphrase; + bool mSitePassphraseProvided; + bool mLocalPassphraseProvided; +}; + +cTWAModeRemoveEncryption::cTWAModeRemoveEncryption() +{ + mSitePassphraseProvided = false; + mLocalPassphraseProvided = false; +} + +cTWAModeRemoveEncryption::~cTWAModeRemoveEncryption() +{ +} + +void cTWAModeRemoveEncryption::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION, TSTRING(_T("")), TSTRING(_T("remove-encryption")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITEPASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCALPASSPHRASE, TSTRING(_T("P")), TSTRING(_T("local-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); + + parser.AddMutEx(cTWAdminCmdLine::KEY_FILE, cTWAdminCmdLine::LOCAL_KEY_FILE); + parser.AddMutEx(cTWAdminCmdLine::KEY_FILE, cTWAdminCmdLine::LOCAL_KEY_FILE); + parser.AddMutEx(cTWAdminCmdLine::KEY_FILE, cTWAdminCmdLine::SITEPASSPHRASE); +} + +bool cTWAModeRemoveEncryption::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + int i; + + FillOutConfigInfo(cf); + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::LOCALPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mLocalPassphraseProvided = true; + mLocalPassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + break; + case cTWAdminCmdLine::SITEPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mSitePassphraseProvided = true; + mSitePassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + break; + case cTWAdminCmdLine::PARAMS: + for (i = 0; i < iter.NumParams(); ++i) + { + // get full path to files + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, iter.ParamAt(i) ) ) + mFileList.push_back( strFullPath ); + else + mFileList.push_back( iter.ParamAt(i) ); + } + break; + } + } + + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +int cTWAModeRemoveEncryption::Execute(cErrorQueue* pQueue) +{ + TSTRING keyfile; + cTWUtil::KeyType keyType; + bool userKnowsLocalPassphrase = false; + bool userKnowsSitePassphrase = false; + + bool bResult = true; + + bool firstFile = true; + bool warningGiven = false; + bool lastMsgWasError = false; // used to send the separating newline to stderr instead of stdout + + if (mFileList.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_FILES_SPECIFIED))); + return 1; + } + + std::list::iterator i; + for (i = mFileList.begin(); i != mFileList.end(); ++i) + { + // These lines print out a blank line if necessary + if (!firstFile) + if (!lastMsgWasError) + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + else + { + TCERR << std::endl; + lastMsgWasError = false; + } + else + firstFile = false; + + if( cFileUtil::IsDir( i->c_str() ) ) + { + // Ignore directories for this particular operation. + cTWUtil::PrintErrorMsg(eTWASkippingDirectory(*i, eError::NON_FATAL)); + lastMsgWasError = true; + } + else + try + { + cFileManipulator manip(i->c_str()); + manip.Init(); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, + _T("%s %s\n"), + TSS_GetString(cTWAdmin, twadmin::STR_EXAMINING_FILE).c_str(), + cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + + if (NotifyFileType(*manip.GetHeaderID(), manip.GetFileVersion(), iUserNotify::V_VERBOSE) == false) + { + throw eTWAFileTypeUnknown(manip.GetFileName()); + } + + // can't decrypt keyfiles + if (*manip.GetHeaderID() == cKeyFile::GetFileHeaderID()) + { + cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CAN_NOT_DECRYPT_KEYFILE), manip.GetFileName(), eError::NON_FATAL)); + lastMsgWasError = true; + bResult = false; + continue; + } + + // if this is a config file, make sure its embedded key is the + // same as the provided keyfile + if (*manip.GetHeaderID() == cConfigFile::GetFileHeaderID()) + { + try + { + cTWUtil::VerifyCfgSiteKey( *i, mSiteKeyFile ); + } + catch (eTWUtil& e) + { + e.SetSupressThird(true); + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + + if (e.GetID() == eError::CalcHash("eTWUtilCorruptedFile")) + cTWUtil::PrintErrorMsg( eTWADecryptCorrupt( manip.GetFileName(), eError::NON_FATAL )); + else + cTWUtil::PrintErrorMsg( eTWADecrypt( manip.GetFileName(), eError::NON_FATAL )); + + //cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_REMOVE_ENCRYPTION_FAILED), manip.GetFileName(), eError::NON_FATAL)); + lastMsgWasError = true; + bResult = false; + continue; + } + } + + if (cFileManipulator::UseSiteKey(*manip.GetHeaderID())) + { + keyType = cTWUtil::KEY_SITE; + keyfile = mSiteKeyFile; + } + else + { + keyType = cTWUtil::KEY_LOCAL; + keyfile = mLocalKeyFile; + } + + if (NotifyEncryptionType(manip.GetEncoding(), iUserNotify::V_VERBOSE) == false) + { + cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_ENCODING_TYPE_UNKNOWN), manip.GetFileName(), eError::NON_FATAL)); + lastMsgWasError = true; + bResult = false; + continue; + } + else if (manip.GetEncoding() != cFileHeader::ASYM_ENCRYPTION) + { + cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_FILE_NOT_ENCRYPED), manip.GetFileName(), eError::NON_FATAL)); + lastMsgWasError = true; + bResult = false; + continue; + } + else + { + // If we got here we have an Asymmetrically encrypted file + + // warn user about removing encryption + if (!warningGiven) + { + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTWAdmin, twadmin::STR_REMOVE_ENCRYPTION_WARNING).c_str()); + TCERR << std::endl; + warningGiven = true; + } + + cKeyFile key; + key.ReadFile( keyfile.c_str() ); + + if (keyType == cTWUtil::KEY_LOCAL) + { + if (!userKnowsLocalPassphrase) + { + cTWUtil::CreatePrivateKey(key, mLocalPassphraseProvided ? mLocalPassphrase.c_str() : 0, keyType); // note: this throws an exception on failure + key.ReleasePrivateKey(); + if (!mLatePassphrase) // force user to enter passphrase each time + userKnowsLocalPassphrase = true; + } + } + else if (keyType == cTWUtil::KEY_SITE) + { + if (!userKnowsSitePassphrase) + { + // Check to see if we can even use the site key to decrypt this file. + cTWUtil::CreatePrivateKey(key, mSitePassphraseProvided ? mSitePassphrase.c_str() : 0, keyType); // note: this throws an exception on failure + key.ReleasePrivateKey(); + if (!mLatePassphrase) // force user to enter passphrase each time + userKnowsSitePassphrase = true; + } + } + else + ASSERT(false); + + try + { + manip.ChangeEncryption(key.GetPublicKey(), NULL, false); + } + catch(eError& e) + { + // Let the user know the decryption failed + e.SetSupressThird( true ); + e.SetFatality( false ); + cTWUtil::PrintErrorMsg( e ); + + if (e.GetID() == eError::CalcHash("eArchiveCrypto")) + cTWUtil::PrintErrorMsg( eTWADecryptCorrupt( manip.GetFileName(), eError::NON_FATAL )); + else + cTWUtil::PrintErrorMsg( eTWADecrypt( manip.GetFileName(), eError::NON_FATAL )); + + lastMsgWasError = true; + bResult = false; + continue; + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPTION_REMOVED).c_str(), + cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + } + } + catch (eFileManip& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + lastMsgWasError = true; + bResult = false; + } + catch (eArchive& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + lastMsgWasError = true; + bResult = false; + } + } + + return bResult == false; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeEncrypt + +class cTWAModeEncrypt : public cTWAModeCommon +{ +public: + cTWAModeEncrypt(); + virtual ~cTWAModeEncrypt(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_ENCRYPT ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION; } +private: + std::list mFileList; + wc16_string mSitePassphrase; + wc16_string mLocalPassphrase; + bool mSitePassphraseProvided; + bool mLocalPassphraseProvided; + bool mbLatePassphrase; +}; + +cTWAModeEncrypt::cTWAModeEncrypt() +{ + mSitePassphraseProvided = false; + mLocalPassphraseProvided = false; + mbLatePassphrase = false; +} + +cTWAModeEncrypt::~cTWAModeEncrypt() +{ +} + +void cTWAModeEncrypt::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_ENCRYPT, TSTRING(_T("")), TSTRING(_T("encrypt")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCALPASSPHRASE, TSTRING(_T("P")), TSTRING(_T("local-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITEPASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); +} + +bool cTWAModeEncrypt::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + int i; + + FillOutConfigInfo(cf); + + TSTRING str; + if(cf->Lookup(TSTRING(_T("LATEPROMPTING")), str)) + { + if (_tcsicmp(str.c_str(), _T("true")) == 0) + mbLatePassphrase = true; + } + + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::PARAMS: + for (i = 0; i < iter.NumParams(); ++i) + { + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, iter.ParamAt(i) ) ) + mFileList.push_back( strFullPath ); + else + mFileList.push_back( iter.ParamAt(i) ); + } + break; + case cTWAdminCmdLine::LOCALPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mLocalPassphraseProvided = true; + mLocalPassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + break; + case cTWAdminCmdLine::SITEPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mSitePassphraseProvided = true; + mSitePassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + break; + } + } + + + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +int cTWAModeEncrypt::Execute(cErrorQueue* pQueue) +{ + cKeyFile siteKeyFile, localKeyFile; + cPrivateKeyProxy siteKey, localKey; + + if (mFileList.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_FILES_SPECIFIED))); + return 1; + } + + bool bResult = true; + std::list::iterator i; + + // We cycle through all the files twice. This first time we + // check for file validity and open any keyfiles needed. + for (i = mFileList.begin(); i != mFileList.end(); /* incrementing done below...*/) + { + try + { + if( cFileUtil::IsDir( i->c_str() ) ) + { + // Ignore directories for this particular operation. + // Note: We don't throw here because we don't want to set bResult to false + cTWUtil::PrintErrorMsg(eTWASkippingDirectory(*i, eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + i = mFileList.erase(i); + continue; + } + else if (!cFileUtil::FileExists(i->c_str())) + { + // tell user we could not open *i + throw eTWAFileNotFound(*i, eError::NON_FATAL); + } + + cFileManipulator manip(i->c_str()); + manip.Init(); + + // can't encrypt keyfiles + if (*manip.GetHeaderID() == cKeyFile::GetFileHeaderID()) + { + throw eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CAN_NOT_DECRYPT_KEYFILE), manip.GetFileName(), eError::NON_FATAL); + } + + if (cFileManipulator::UseSiteKey(*manip.GetHeaderID())) + { + if (!siteKeyFile.KeysLoaded()) + cTWUtil::OpenKeyFile(siteKeyFile, mSiteKeyFile); + } + else + { + if (!localKeyFile.KeysLoaded()) + cTWUtil::OpenKeyFile(localKeyFile, mLocalKeyFile); + } + + // increment the iterator + ++i; + } + catch (eError& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + TCERR << std::endl; // extra newline to separate filenames + + // erase this file so that it is skipped in the next round + i = mFileList.erase(i); + bResult = false; + continue; + } + } + + // On this second pass we go through and convert all files + for (i = mFileList.begin(); i != mFileList.end(); ++i) + { + if( cFileUtil::IsDir( i->c_str() ) ) + { + // Ignore directories for this particular operation. + } + else if (!cFileUtil::FileExists(i->c_str())) + { + // tell user we could not open *i + bResult = false; + } + else + try + { + cFileManipulator manip(i->c_str()); + manip.Init(); + + if (*manip.GetHeaderID() == cKeyFile::GetFileHeaderID()) + { + continue; + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, + _T("%s %s\n"), + TSS_GetString(cTWAdmin, twadmin::STR_EXAMINING_FILE).c_str(), + cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + + if (NotifyFileType(*manip.GetHeaderID(), manip.GetFileVersion(), iUserNotify::V_VERBOSE) == false) + { + cTWUtil::PrintErrorMsg(eTWAFileTypeUnknown(manip.GetFileName(), eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + bResult = false; + } + + if (NotifyEncryptionType(manip.GetEncoding(), iUserNotify::V_VERBOSE) == false) + { + cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_ENCODING_TYPE_UNKNOWN), manip.GetFileName(), eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + bResult = false; + } + else if (manip.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + cTWUtil::PrintErrorMsg(eTWAEncryptionChange(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_FILE_ALREADY_ENCRYPTED), manip.GetFileName(), eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + bResult = false; + } + else + { + cPrivateKeyProxy* pPrivateKey; + + if (cFileManipulator::UseSiteKey(*manip.GetHeaderID())) + { + if (mbLatePassphrase || !siteKey.Valid()) + cTWUtil::CreatePrivateKey(siteKey, siteKeyFile, mSitePassphraseProvided ? mSitePassphrase.c_str() : 0, cTWUtil::KEY_SITE); + + pPrivateKey = &siteKey; + } + else + { + if (mbLatePassphrase || !localKey.Valid()) + cTWUtil::CreatePrivateKey(localKey, localKeyFile, mLocalPassphraseProvided ? mLocalPassphrase.c_str() : 0, cTWUtil::KEY_LOCAL); + + pPrivateKey = &localKey; + } + + try + { + manip.ChangeEncryption(NULL, pPrivateKey->GetKey(), false); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPTION_SUCCEEDED).c_str(), + cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, + TSS_GetString(cTW, tw::STR_NEWLINE).c_str(), + cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + } + catch (eFileManip& e) + { + cTWUtil::PrintErrorMsg(e); + TCERR << std::endl; // extra newline to separate filenames + bResult = false; + } + } + } + catch (eFileManip&) + { + continue; + } + } + + return bResult == false; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeExamine + +class cTWAModeExamine : public cTWAModeCommon +{ +public: + cTWAModeExamine(); + virtual ~cTWAModeExamine(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_EXAMINE ); } + virtual bool LoadConfigFile() { return true; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION; } +private: + std::list mFileList; +}; + +cTWAModeExamine::cTWAModeExamine() +{ +} + +cTWAModeExamine::~cTWAModeExamine() +{ +} + +void cTWAModeExamine::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_EXAMINE, TSTRING(_T("")), TSTRING(_T("examine")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); +} + +bool cTWAModeExamine::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + int i; + + FillOutConfigInfo(cf); + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::PARAMS: + for (i = 0; i < iter.NumParams(); ++i) + { + TSTRING strFullPath; + if( iFSServices::GetInstance()->FullPath( strFullPath, iter.ParamAt(i) ) ) + mFileList.push_back( strFullPath ); + else + mFileList.push_back( iter.ParamAt(i) ); + } + break; + } + } + + // check that the config file and site key file are in sync... + // + if( ! mCfgFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mCfgFilePath, mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +int cTWAModeExamine::Execute(cErrorQueue* pQueue) +{ + if (mFileList.empty()) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_NO_FILES_SPECIFIED))); + return 1; + } + + bool bResult = true; + + // Open site and local key up front so we can warn if they fail opening + cKeyFile siteKey, localKey; + try + { + siteKey.ReadFile(mSiteKeyFile.c_str()); + } + catch (eKeyFile& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + bResult = false; + } + catch (eError&) + { + } + + try + { + localKey.ReadFile(mLocalKeyFile.c_str()); + } + catch (eKeyFile& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + bResult = false; + } + catch (eError&) + { + } + + // now iteratate over files to examine + std::list::iterator i; + for (i = mFileList.begin(); i != mFileList.end(); ++i) + { + if( cFileUtil::IsDir(i->c_str())) + { + //Ignore directories in examine encryption mode. + cTWUtil::PrintErrorMsg(eTWASkippingDirectory(*i, eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + } + else if (!cFileUtil::FileExists(i->c_str())) + { + // tell user we could not open *i + cTWUtil::PrintErrorMsg(eTWAFileNotFound(*i, eError::NON_FATAL)); + TCERR << std::endl; // extra newline to separate filenames + bResult = false; + } + else + try + { + cFileManipulator manip(i->c_str()); + manip.Init(); + + // print out: "File: filename.ext" + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTWAdmin, twadmin::STR_FILE).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), cDisplayEncoder::EncodeInline( manip.GetFileName() ).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTWAdmin, twadmin::STR_ENDQUOTE_NEWLINE).c_str()); + + NotifyFileType(*manip.GetHeaderID(), manip.GetFileVersion(), iUserNotify::V_NORMAL); + NotifyEncryptionType(manip.GetEncoding(), iUserNotify::V_NORMAL); + + // Try different keys to see if they decrypt this file + if (manip.GetEncoding() == cFileHeader::ASYM_ENCRYPTION) + { + // Output the keys that decrypt the file. + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_KEYS_DECRYPT ).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTW, tw::STR_NEWLINE ).c_str()); + + bool siteDecrypts = false, localDecrypts = false; + + if (siteKey.KeysLoaded()) + try + { + if (manip.TestDecryption(*siteKey.GetPublicKey(), false) != false) + { + siteDecrypts = true; + + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTWAdmin, twadmin::STR_SITEKEYFILE ).c_str()); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, cDisplayEncoder::EncodeInline( mSiteKeyFile ).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE ).c_str()); + } + } + catch (eError&) {} + + if (localKey.KeysLoaded()) + try + { + if (manip.TestDecryption(*localKey.GetPublicKey(), false) != false) + { + localDecrypts = true; + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTWAdmin, twadmin::STR_LOCALKEYFILE ).c_str()); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, cDisplayEncoder::EncodeInline( mLocalKeyFile ).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE ).c_str()); + } + } + catch (eError&) {} + } + TCOUT << std::endl; + } + catch (eFileManip& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + TCERR << std::endl; + bResult = false; + } + } + + return bResult == false; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeGenerateKeys + +class cTWAModeGenerateKeys : public cTWAModeCommon +{ +public: + cTWAModeGenerateKeys(); + virtual ~cTWAModeGenerateKeys(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_GENERATE_KEYS ); } + virtual bool LoadConfigFile() { return false; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_GENERATE_KEYS; } + +private: + bool mSiteProvided; // A site passphrase has been passed. + wc16_string mSitePassphrase; + bool mLocalProvided; // A local passphrase has been passed. + wc16_string mLocalPassphrase; + bool mGenerateSite; // A Site key has been specified. + bool mGenerateLocal; // A Local key has been specified. +}; + +cTWAModeGenerateKeys::cTWAModeGenerateKeys() +{ + mLocalProvided = false; + mSiteProvided = false; + mGenerateSite = false; + mGenerateLocal = false; +} + +cTWAModeGenerateKeys::~cTWAModeGenerateKeys() +{ +} + +void cTWAModeGenerateKeys::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_GENERATE_KEYS, TSTRING(_T("")), TSTRING(_T("generate-keys")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITEPASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCALPASSPHRASE, TSTRING(_T("P")), TSTRING(_T("local-passphrase")), cCmdLineParser::PARAM_ONE); +} + +bool cTWAModeGenerateKeys::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + TSTRING str; + + // Note: we don't use the config file for anything any more. + + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::SITEPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mSitePassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mSiteProvided = true; + break; + case cTWAdminCmdLine::LOCALPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mLocalPassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mLocalProvided = true; + break; + case cTWAdminCmdLine::SITE_KEY_FILE: + mGenerateSite = true; + break; + case cTWAdminCmdLine::LOCAL_KEY_FILE: + mGenerateLocal = true; + break; + } + } + + if (mSiteProvided || mLocalProvided) + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_PASSPHRASES).c_str()); + + return true; +} + +int cTWAModeGenerateKeys::Execute(cErrorQueue* pQueue) +{ + int i; + + if (!mGenerateSite && !mGenerateLocal) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYS_NOT_SPECIFIED))); + return 1; + } + + if ((mGenerateSite && mSiteKeyFile.empty()) || + (mGenerateLocal && mLocalKeyFile.empty())) + { + // This case should not occur (it should be caught by Init() logic), but in case it does we will spit out + // a generic error string. + ASSERT(false); + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYS_NOT_SPECIFIED))); + return 1; + } + + if (!mGenerateSite && mSiteProvided) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_LONE_SITE_PASSPHRASE))); + return 1; + } + + if (!mGenerateLocal && mLocalProvided) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_LONE_LOCAL_PASSPHRASE))); + return 1; + } + + if( (mSiteProvided && !mGenerateSite) || (mLocalProvided && !mGenerateLocal) ) + { + //This is an error, a passphrase should not be specified if the corresponding key has not been passed. + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_PASSPHRASE_NOKEY))); + return 1; + } + + if (mSiteKeyFile == mLocalKeyFile) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEY_FILENAMES_IDENTICAL))); + return 1; + } + + if (mGenerateSite && cFileUtil::FileExists(mSiteKeyFile)) + { + TSTRING prompt; + prompt += TSS_GetString(cTWAdmin, twadmin::STR_SITEKEY_EXISTS_1); + prompt += cDisplayEncoder::EncodeInline( mSiteKeyFile ); + prompt += TSS_GetString(cTWAdmin, twadmin::STR_SITEKEY_EXISTS_2); + + if (cTWUtil::ConfirmYN(prompt.c_str()) == false) + return 1; + } + + if (mGenerateLocal && cFileUtil::FileExists(mLocalKeyFile)) + { + TSTRING prompt; + prompt += TSS_GetString(cTWAdmin, twadmin::STR_LOCALKEY_EXISTS_1); + prompt += cDisplayEncoder::EncodeInline( mLocalKeyFile ); + prompt += TSS_GetString(cTWAdmin, twadmin::STR_LOCALKEY_EXISTS_2); + + if (cTWUtil::ConfirmYN(prompt.c_str()) == false) + return 1; + } + + // + // make sure that we can write to both of the files before we continue + // + if(mGenerateLocal) + cFileUtil::TestFileWritable(mLocalKeyFile); + if(mGenerateSite) + cFileUtil::TestFileWritable(mSiteKeyFile); + + wc16_string verify; + + bool bPrintedPassphraseHint = false; + + if (mGenerateSite) + { + if (!mSiteProvided) + { + // give the user a passphrase hint... + // + if(! bPrintedPassphraseHint) + { + bPrintedPassphraseHint = true; + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_PASSPHRASE_HINT).c_str() ); + } + + for (i=1; ; i++) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_SITE_PASS); + cTWUtil::GetString(mSitePassphrase); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_VERIFY_SITE_PASS); + cTWUtil::GetString(verify); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + if ( 0 == verify.compare( mSitePassphrase ) ) + break; + + TCOUT << TSS_GetString(cTW, tw::STR_ERR_WRONG_PASSPHRASE_SITE) << std::endl; + + if (i == 3) + return 1; + } + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_SITEKEY).c_str(), + cDisplayEncoder::EncodeInline( mSiteKeyFile ).c_str()); + + // backup current file if it exists + cFileUtil::BackupFile(mSiteKeyFile); + + if (GenerateKey(mSiteKeyFile.c_str(), mSitePassphrase) == false) + return 1; + } + + if (mGenerateLocal) + { + if (!mLocalProvided) + { + // give the user a passphrase hint... + // + if(! bPrintedPassphraseHint) + { + bPrintedPassphraseHint = true; + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_PASSPHRASE_HINT).c_str() ); + } + + for (i=1; ; i++) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_LOCAL_PASS); + cTWUtil::GetString(mLocalPassphrase); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_VERIFY_LOCAL_PASS); + cTWUtil::GetString(verify); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + if ( 0 == verify.compare( mLocalPassphrase ) ) + break; + + TCOUT << TSS_GetString(cTW, tw::STR_ERR_WRONG_PASSPHRASE_LOCAL) << std::endl; + + if (i == 3) + return 1; + } + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_LOCALKEY).c_str(), + cDisplayEncoder::EncodeInline( mLocalKeyFile ).c_str()); + + // backup current file if it exists + cFileUtil::BackupFile(mLocalKeyFile); + + if (GenerateKey(mLocalKeyFile.c_str(), mLocalPassphrase) == false) + return 1; + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// cTWAModeChangePassphrases + +static bool ChangePassphrase( + const TCHAR* keyPath, wc16_string passphraseOld, wc16_string passphrase) +{ + // in order to leave original password data intact upon return, + // we must allocate a BIGENDIAN copy + // and delete it before we return. + // auto_ptr does not help (won't work with arrays). + size_t passphraseLenOld = passphraseOld.length() * sizeof(WCHAR16); + size_t passphraseLen = passphrase .length() * sizeof(WCHAR16); + int8 * passphraseCopyOld = new int8[passphraseLenOld]; + int8 * passphraseCopy = new int8[passphraseLen]; +#ifdef WORDS_BIGENDIAN + memcpy(passphraseCopyOld, passphraseOld.data(), passphraseLenOld); + memcpy(passphraseCopy, passphrase .data(), passphraseLen); +#else + swab(passphraseOld.data(), passphraseCopyOld, passphraseLenOld); + swab(passphrase .data(), passphraseCopy, passphraseLen); +#endif + + bool result; + try { + cKeyFile keyfile; + keyfile.ReadFile(keyPath); + keyfile.ChangePassphrase( + passphraseCopyOld, passphraseLenOld, + passphraseCopy, passphraseLen); + keyfile.WriteFile(keyPath); + result = true; + } + catch (eKeyFile & e) + { + cTWUtil::PrintErrorMsg(e); + result = false; + } + delete[] passphraseCopyOld; + delete[] passphraseCopy; + return result; +} + +class cTWAModeChangePassphrases : public cTWAModeCommon +{ +public: + cTWAModeChangePassphrases(); + virtual ~cTWAModeChangePassphrases(); + + virtual void InitCmdLineParser(cCmdLineParser& parser); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& parser); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CHANGE_PASSPHRASES ); } + virtual bool LoadConfigFile() { return false; } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_CHANGE_PASSPHRASES; } + +private: + bool mSiteProvidedOld; // A site passphrase-old has been passed. + wc16_string mSitePassphraseOld; + bool mLocalProvidedOld; // A local passphrase-old has been passed. + wc16_string mLocalPassphraseOld; + bool mSiteProvided; // A site passphrase has been passed. + wc16_string mSitePassphrase; + bool mLocalProvided; // A local passphrase has been passed. + wc16_string mLocalPassphrase; + bool mChangeSite; // A Site key has been specified. + bool mChangeLocal; // A Local key has been specified. +}; + +cTWAModeChangePassphrases::cTWAModeChangePassphrases() +{ + mLocalProvidedOld = false; + mSiteProvidedOld = false; + mLocalProvided = false; + mSiteProvided = false; + mChangeSite = false; + mChangeLocal = false; +} + +cTWAModeChangePassphrases::~cTWAModeChangePassphrases() +{ +} + +void cTWAModeChangePassphrases::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon(parser); + + parser.AddArg(cTWAdminCmdLine::MODE_CHANGE_PASSPHRASES,TSTRING(_T("")), TSTRING(_T("change-passphrases")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWAdminCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITEPASSPHRASE, TSTRING(_T("Q")), TSTRING(_T("site-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCALPASSPHRASE, TSTRING(_T("P")), TSTRING(_T("local-passphrase")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::SITEPASSPHRASEOLD, TSTRING(_T("")), TSTRING(_T("site-passphrase-old")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWAdminCmdLine::LOCALPASSPHRASEOLD, TSTRING(_T("")), TSTRING(_T("local-passphrase-old")), cCmdLineParser::PARAM_ONE); +} + +bool cTWAModeChangePassphrases::Init(const cConfigFile* cf, const cCmdLineParser& parser) +{ + TSTRING str; + + // Note: we don't use the config file for anything any more. + + FillOutCmdLineInfo(parser); + + cCmdLineIter iter(parser); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::SITEPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mSitePassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mSiteProvided = true; + break; + case cTWAdminCmdLine::LOCALPASSPHRASE: + ASSERT(iter.NumParams() == 1); + mLocalPassphrase = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mLocalProvided = true; + break; + case cTWAdminCmdLine::SITEPASSPHRASEOLD: + ASSERT(iter.NumParams() == 1); + mSitePassphraseOld = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mSiteProvidedOld = true; + break; + case cTWAdminCmdLine::LOCALPASSPHRASEOLD: + ASSERT(iter.NumParams() == 1); + mLocalPassphraseOld = cStringUtil::TstrToWstr(iter.ParamAt(0)); + mLocalProvidedOld = true; + break; + case cTWAdminCmdLine::SITE_KEY_FILE: + mChangeSite = true; + break; + case cTWAdminCmdLine::LOCAL_KEY_FILE: + mChangeLocal = true; + break; + } + } + + if ((mSiteProvidedOld && mSiteProvided) || (mLocalProvidedOld && mLocalProvided)) + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_PASSPHRASES).c_str()); + + return true; +} + +int cTWAModeChangePassphrases::Execute(cErrorQueue* pQueue) +{ + int i; + bool bSiteProvided = mSiteProvided || mSiteProvidedOld; + bool bLocalProvided = mLocalProvided || mLocalProvidedOld; + + if (!mChangeSite && !mChangeLocal) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYS_NOT_SPECIFIED))); + return 1; + } + + if ((mChangeSite && mSiteKeyFile.empty()) || + (mChangeLocal && mLocalKeyFile.empty())) + { + // This case should not occur (it should be caught by Init() logic), but in case it does we will spit out + // a generic error string. + ASSERT(false); + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEYS_NOT_SPECIFIED))); + return 1; + } + + if (!mChangeSite && bSiteProvided) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_LONE_SITE_PASSPHRASE))); + return 1; + } + + if (!mChangeLocal && bLocalProvided) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_LONE_LOCAL_PASSPHRASE))); + return 1; + } + + if( (bSiteProvided && !mChangeSite) || (bLocalProvided && !mChangeLocal) ) + { + //This is an error, a passphrase should not be specified if the corresponding key has not been passed. + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_PASSPHRASE_NOKEY))); + return 1; + } + + if (mSiteKeyFile == mLocalKeyFile) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_KEY_FILENAMES_IDENTICAL))); + return 1; + } + + if (mChangeSite && !cFileUtil::FileExists(mSiteKeyFile)) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_SITE_KEY_DOESNT_EXIST))); + return 1; + } + + if (mChangeLocal && !cFileUtil::FileExists(mLocalKeyFile)) + { + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTWAdmin, twadmin::STR_ERR2_LOCAL_KEY_DOESNT_EXIST))); + return 1; + } + + // + // make sure that we can write to both of the files before we continue + // + if(mChangeLocal) + cFileUtil::TestFileWritable(mLocalKeyFile); + if(mChangeSite) + cFileUtil::TestFileWritable(mSiteKeyFile); + + wc16_string verify; + + bool bPrintedPassphraseHint = false; + + if (mChangeSite) + { + if (!mSiteProvidedOld) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_SITE_PASS_OLD); + cTWUtil::GetString(mSitePassphraseOld); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + } + if (!mSiteProvided) + { + // give the user a passphrase hint... + // + if(! bPrintedPassphraseHint) + { + bPrintedPassphraseHint = true; + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_PASSPHRASE_HINT).c_str() ); + } + + for (i=1; ; i++) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_SITE_PASS); + cTWUtil::GetString(mSitePassphrase); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_VERIFY_SITE_PASS); + cTWUtil::GetString(verify); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + if ( 0 == verify.compare( mSitePassphrase ) ) + break; + + TCOUT << TSS_GetString(cTW, tw::STR_ERR_WRONG_PASSPHRASE_SITE) << std::endl; + + if (i == 3) + return 1; + } + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_SITEKEY).c_str(), + cDisplayEncoder::EncodeInline( mSiteKeyFile ).c_str()); + + // backup current file if it exists + cFileUtil::BackupFile(mSiteKeyFile); + + if (ChangePassphrase(mSiteKeyFile.c_str(), mSitePassphraseOld, mSitePassphrase) == false) + return 1; + } + + if (mChangeLocal) + { + if (!mLocalProvidedOld) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_LOCAL_PASS_OLD); + cTWUtil::GetString(mLocalPassphraseOld); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + } + if (!mLocalProvided) + { + // give the user a passphrase hint... + // + if(! bPrintedPassphraseHint) + { + bPrintedPassphraseHint = true; + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, TSS_GetString(cTWAdmin, twadmin::STR_PASSPHRASE_HINT).c_str() ); + } + + for (i=1; ; i++) + { + cTWUtil::NoEcho noEcho; + // Note: Since we are interacting directly with the user here, + // I think it is o.k. to use cout directly. + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_ENTER_LOCAL_PASS); + cTWUtil::GetString(mLocalPassphrase); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + TCOUT << TSS_GetString(cTWAdmin, twadmin::STR_VERIFY_LOCAL_PASS); + cTWUtil::GetString(verify); + TCOUT << TSS_GetString(cTW, tw::STR_NEWLINE); + + if ( 0 == verify.compare( mLocalPassphrase ) ) + break; + + TCOUT << TSS_GetString(cTW, tw::STR_ERR_WRONG_PASSPHRASE_LOCAL) << std::endl; + + if (i == 3) + return 1; + } + } + + iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, + TSS_GetString(cTWAdmin, twadmin::STR_KEYGEN_VERBOSE_LOCALKEY).c_str(), + cDisplayEncoder::EncodeInline( mLocalKeyFile ).c_str()); + + // backup current file if it exists + cFileUtil::BackupFile(mLocalKeyFile); + + if (ChangePassphrase(mLocalKeyFile.c_str(), mLocalPassphraseOld, mLocalPassphrase) == false) + return 1; + } + + return 0; +} + + +//############################################################################# +// cTWAModeHelp : A mode for supplying mode specific usage statements +//############################################################################# + +class cTWAModeHelp : public iTWAMode +{ +public: + cTWAModeHelp() {} + virtual ~cTWAModeHelp() {} + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual cTWAdminCmdLine::CmdLineArgs GetModeID ( void ) const; + virtual TSTRING GetModeUsage( ) { return _T(""); } //TODO: dra Output something here? + +private: + // A list of modes to output usage statements for: + std::set< TSTRING > mModes; + std::set< TSTRING > mPrinted; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GetModeID +/////////////////////////////////////////////////////////////////////////////// +cTWAdminCmdLine::CmdLineArgs cTWAModeHelp::GetModeID( void ) const +{ + return cTWAdminCmdLine::MODE_HELP; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWAModeHelp::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // We're only interested in one parameter, that being help. Anything else + // passed to this mode should be a cmdlineparser error. + cmdLine.AddArg(cTWAdminCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY, true ); + cmdLine.AddArg(cTWAdminCmdLine::MODE_HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_HELP_ALL, TSTRING(_T("")), TSTRING(_T("all")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_CREATE_CONFIG, TSTRING(_T("F")), TSTRING(_T("create-cfgfile")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_PRINT_CONFIG, TSTRING(_T("f")), TSTRING(_T("print-cfgfile")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_CREATE_POLICY, TSTRING(_T("P")), TSTRING(_T("create-polfile")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_PRINT_POLICY, TSTRING(_T("p")), TSTRING(_T("print-polfile")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION, TSTRING(_T("R")), TSTRING(_T("remove-encryption")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_ENCRYPT, TSTRING(_T("E")), TSTRING(_T("encrypt")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_EXAMINE, TSTRING(_T("e")), TSTRING(_T("examine")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_GENERATE_KEYS, TSTRING(_T("G")), TSTRING(_T("generate-keys")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWAdminCmdLine::MODE_CHANGE_PASSPHRASES,TSTRING(_T("C")), TSTRING(_T("change-passphrases")), cCmdLineParser::PARAM_MANY); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWAModeHelp::Init(const cConfigFile* cf, const cCmdLineParser& cmdLine) +{ + cCmdLineIter iter(cmdLine); + + // Grab the arguments from the help parameter: + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWAdminCmdLine::MODE_HELP: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + { + mModes.insert( iter.ParamAt(i) ); + } + } + break; + case cTWAdminCmdLine::MODE: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + { + mModes.insert( iter.ParamAt(i) ); + } + } + break; + case cTWAdminCmdLine::MODE_HELP_ALL: //fall through + case cTWAdminCmdLine::MODE_CREATE_CONFIG: //fall through + case cTWAdminCmdLine::MODE_PRINT_CONFIG: //fall through + case cTWAdminCmdLine::MODE_CREATE_POLICY: //fall through + case cTWAdminCmdLine::MODE_PRINT_POLICY: //fall through + case cTWAdminCmdLine::MODE_REMOVE_ENCRYPTION: //fall through + case cTWAdminCmdLine::MODE_ENCRYPT: //fall through + case cTWAdminCmdLine::MODE_EXAMINE: //fall through + case cTWAdminCmdLine::MODE_GENERATE_KEYS: + case cTWAdminCmdLine::MODE_CHANGE_PASSPHRASES: + { + int i; + TSTRING str = iter.ActualParam(); + // Kill off the initial "--" or "-" + str.erase( 0, 1 ); + if( str.length() != 1) + str.erase( 0, 1 ); + + // push back the parameter that was actually passed. + mModes.insert( str ); + // grab all the "parameters" following the mode/switch, since + // they may be valid modes without the "--" prepended. + for( i = 0; i < iter.NumParams(); ++i ) + mModes.insert( iter.ParamAt(i) ); + } + break; + default: + // should I do anything, or just ignore this? + // cmdlineparser will catch the bad args. + ; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWAModeHelp::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWAModeHelp::Execute"); + + // The iterator we will use to traverse the list of arguments: + std::set< TSTRING >::iterator it = mModes.begin(); + + // We'll want to output the version information, regardless: + TCOUT<< TSS_GetString(cTWAdmin, twadmin::STR_TWADMIN_VERSION ) << std::endl; + TCOUT<< TSS_GetString(cTW, tw::STR_VERSION ) << std::endl; + + if( it == mModes.end() ) // all that was passed was --help + { + // Output a shorter usage statement for each mode + TCOUT<< TSS_GetString(cTWAdmin, twadmin::STR_TWADMIN_USAGE_SUMMARY); + // + //That's it, return + return 1; + } + + for( ; it != mModes.end(); ++it ) + { + if( _tcscmp( (*it).c_str(), _T("all")) == 0 ) + { + //Since --help all was passed, emit all help messages and return. + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_CFGFILE ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_CFGFILE ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_POLFILE ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_POLFILE ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_REMOVE_ENCRYPTION ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_ENCRYPT ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_EXAMINE ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_GENERATE_KEYS ); + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CHANGE_PASSPHRASES ); + + //We're done, return + return 1; + } + } + + //We need some subset of the usage statements. Figure out which modes have + //been specified: + it = mModes.begin(); + for( ; it != mModes.end(); ++it ) + { + if ( _tcscmp( (*it).c_str(), _T("create-cfgfile") ) == 0 || _tcscmp( (*it).c_str(), _T("F") ) == 0) + { + //make sure we don't print the same help twice... + if( mPrinted.find(_T("create-cfgfile")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_CFGFILE ); + mPrinted.insert(_T("create-cfgfile")); + } + } + else if( _tcscmp( (*it).c_str(), _T("print-cfgfile") ) == 0 || _tcscmp( (*it).c_str(), _T("f") ) == 0) + { + if( mPrinted.find(_T("print-cfgfile")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_CFGFILE ); + mPrinted.insert(_T("print-cfgfile")); + } + } + else if( _tcscmp( (*it).c_str(), _T("create-polfile") ) == 0 || _tcscmp( (*it).c_str(), _T("P") ) == 0) + { + if( mPrinted.find(_T("create-polfile")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CREATE_POLFILE ); + mPrinted.insert(_T("create-polfile")); + } + } + else if( _tcscmp( (*it).c_str(), _T("print-polfile") ) == 0 || _tcscmp( (*it).c_str(), _T("p") ) == 0) + { + if( mPrinted.find(_T("print-polfile")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_PRINT_POLFILE ); + mPrinted.insert(_T("print-polfile")); + } + } + else if( _tcscmp( (*it).c_str(), _T("remove-encryption") ) == 0 || _tcscmp( (*it).c_str(), _T("R") ) == 0) + { + if( mPrinted.find(_T("remove-encryption")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_REMOVE_ENCRYPTION ); + mPrinted.insert(_T("remove-encryption")); + } + } + else if( _tcscmp( (*it).c_str(), _T("encrypt") ) == 0 || _tcscmp( (*it).c_str(), _T("E") ) == 0) + { + if( mPrinted.find(_T("encrypt")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_ENCRYPT ); + mPrinted.insert(_T("encrypt")); + } + } + else if( _tcscmp( (*it).c_str(), _T("examine") ) == 0 || _tcscmp( (*it).c_str(), _T("e") ) == 0) + { + if( mPrinted.find(_T("examine")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_EXAMINE ); + mPrinted.insert(_T("examine")); + } + } + else if( _tcscmp( (*it).c_str(), _T("generate-keys") ) == 0 || _tcscmp( (*it).c_str(), _T("G") ) == 0) + { + if( mPrinted.find(_T("generate-keys")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_GENERATE_KEYS ); + mPrinted.insert(_T("generate-keys")); + } + } + else if( _tcscmp( (*it).c_str(), _T("change-passphrases") ) == 0 || _tcscmp( (*it).c_str(), _T("C") ) == 0) + { + if( mPrinted.find(_T("change-passphrases")) == mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWAdmin, twadmin::STR_TWADMIN_HELP_CHANGE_PASSPHRASES ); + mPrinted.insert(_T("change-passphrases")); + } + } + else + { + cTWUtil::PrintErrorMsg( eTWAInvalidHelpMode( (*it), eError::NON_FATAL ) ); + TCOUT << std::endl; + // emit error string, this mode does not exist + } + } + + //Everything went okay + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// Version Mode +/////////////////////////////////////////////////////////////////////////////// +class cTWAModeVersion : public iTWAMode +{ +public: + cTWAModeVersion() {} + virtual ~cTWAModeVersion() {} + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine) { ASSERT(false); } + virtual bool Init (const cConfigFile* cf, const cCmdLineParser& cmdLine) { ASSERT(false); return true; } + virtual int Execute (cErrorQueue* pQueue) { ASSERT(false); return 0; } + virtual TSTRING GetModeUsage( ) { ASSERT(false); return _T(""); } + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const { return cTWAdminCmdLine::MODE_VERSION; } +private: +}; + + + +//############################################################################# + +/////////////////////////////////////////////////////////////////////////////// +// cTWAdminCmdLine::GetMode() +// + +iTWAMode* cTWAdminCmdLine::GetMode(int argc, const TCHAR *const * argv) +{ + // note -- it is assumed the executable name is the first parameter + if(argc < 2) + { + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTWAdmin, twadmin::STR_TWADMIN_VERSION).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTW, tw::STR_VERSION).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTW, tw::STR_GET_HELP).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + return NULL; + } + + int mode = MODE; + const TCHAR* pcMode; + if(_tcscmp(argv[1], _T("-m")) == 0) + { + if(argc < 3) + { + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTWAdmin, twadmin::STR_TWADMIN_VERSION).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTW, tw::STR_VERSION).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + + cTWUtil::PrintErrorMsg(eBadCmdLine(TSS_GetString(cTW, tw::STR_ERR_NO_MODE), eError::SUPRESS_THIRD_MSG)); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTW, tw::STR_GET_HELP).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + + return NULL; + } + pcMode = argv[2]; + if (_tcscmp(argv[2], _T("F")) == 0) + mode = MODE_CREATE_CONFIG; + else if (_tcscmp(argv[2], _T("f")) == 0) + mode = MODE_PRINT_CONFIG; + else if (_tcscmp(argv[2], _T("P")) == 0) + mode = MODE_CREATE_POLICY; + else if (_tcscmp(argv[2], _T("p")) == 0) + mode = MODE_PRINT_POLICY; + else if (_tcscmp(argv[2], _T("R")) == 0) + mode = MODE_REMOVE_ENCRYPTION; + else if (_tcscmp(argv[2], _T("E")) == 0) + mode = MODE_ENCRYPT; + else if (_tcscmp(argv[2], _T("e")) == 0) + mode = MODE_EXAMINE; + else if (_tcscmp(argv[2], _T("G")) == 0) + mode = MODE_GENERATE_KEYS; + else if (_tcscmp(argv[2], _T("C")) == 0) + mode = MODE_CHANGE_PASSPHRASES; + } + else + { + pcMode = argv[1]; + if (_tcscmp(argv[1], _T("--create-cfgfile")) == 0) + mode = MODE_CREATE_CONFIG; + else if (_tcscmp(argv[1], _T("--print-cfgfile")) == 0) + mode = MODE_PRINT_CONFIG; + else if (_tcscmp(argv[1], _T("--create-polfile")) == 0) + mode = MODE_CREATE_POLICY; + else if (_tcscmp(argv[1], _T("--print-polfile")) == 0) + mode = MODE_PRINT_POLICY; + else if (_tcscmp(argv[1], _T("--remove-encryption")) == 0) + mode = MODE_REMOVE_ENCRYPTION; + else if (_tcscmp(argv[1], _T("--encrypt")) == 0) + mode = MODE_ENCRYPT; + else if (_tcscmp(argv[1], _T("--examine")) == 0) + mode = MODE_EXAMINE; + else if (_tcscmp(argv[1], _T("--generate-keys")) == 0) + mode = MODE_GENERATE_KEYS; + else if (_tcscmp(argv[1], _T("--change-passphrases")) == 0) + mode = MODE_CHANGE_PASSPHRASES; + else if (_tcscmp(argv[1], _T("--version")) == 0) + mode = MODE_VERSION; + } + + // check for --help flag anywhere in the args + int i; + for (i = 1; i < argc; ++i) + if (_tcscmp(argv[i], _T("--help")) == 0 || _tcscmp(argv[i], _T("-?")) == 0) + { + mode = MODE_HELP; + break; + } + + if(mode == MODE) + { + // unknown mode switch + cDebug d("cTWAdminCmdLine::GetMode"); + d.TraceError("Error: Bad mode switch: %s\n", pcMode); + + TSTRING estr = TSS_GetString(cTW, tw::STR_ERR2_BAD_MODE_SWITCH); + estr.append(pcMode); + cTWUtil::PrintErrorMsg(eBadModeSwitch(estr, eError::SUPRESS_THIRD_MSG)); + + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, _T("%s"), TSS_GetString(cTW, tw::STR_GET_HELP).c_str()); + iUserNotify::GetInstance()->Notify(iUserNotify::V_SILENT, TSS_GetString(cTW, tw::STR_NEWLINE).c_str()); + return NULL; + } + + + iTWAMode* pRtn = 0; + switch(mode) + { + case MODE_CREATE_CONFIG: + pRtn = new cTWAModeCreateCfg; + break; + case MODE_CREATE_POLICY: + pRtn = new cTWAModeCreatePol; + break; + case MODE_PRINT_CONFIG: + pRtn = new cTWAModePrintCfg; + break; + case MODE_PRINT_POLICY: + pRtn = new cTWAModePrintPol; + break; + case MODE_REMOVE_ENCRYPTION: + pRtn = new cTWAModeRemoveEncryption; + break; + case MODE_ENCRYPT: + pRtn = new cTWAModeEncrypt; + break; + case MODE_EXAMINE: + pRtn = new cTWAModeExamine; + break; + case MODE_GENERATE_KEYS: + pRtn = new cTWAModeGenerateKeys; + break; + case MODE_CHANGE_PASSPHRASES: + pRtn = new cTWAModeChangePassphrases; + break; + case MODE_HELP: + pRtn = new cTWAModeHelp; + break; + case MODE_VERSION: + pRtn = new cTWAModeVersion; + break; + default: + ASSERT(false); + } + + return pRtn; +} + +// Calls UserNotify(V_VERBOSE, ...) to print out type of file specified in cFileHeaderID. +// Returns false if cFileHeaderID not recognized. +// Used in changing and removing encryption algorithms +static bool NotifyFileType(const cFileHeaderID& id, uint32 version, iUserNotify::VerboseLevel vl) +{ + if (id == cFCODatabaseFile::GetFileHeaderID()) + { + iUserNotify::GetInstance()->Notify(vl, + TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_DB).c_str(), + (version & 0xff000000) >> 24, + (version & 0x00ff0000) >> 16, + (version & 0x0000ff00) >> 8, + (version & 0x000000ff)); + return true; + } + else if (id == cFCOReport::GetFileHeaderID()) + { + iUserNotify::GetInstance()->Notify(vl, + TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_REP).c_str(), + (version & 0xff000000) >> 24, + (version & 0x00ff0000) >> 16, + (version & 0x0000ff00) >> 8, + (version & 0x000000ff)); + return true; + } + else if (id == cConfigFile::GetFileHeaderID()) + { + iUserNotify::GetInstance()->Notify(vl, + TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_CFG).c_str(), + (version & 0xff000000) >> 24, + (version & 0x00ff0000) >> 16, + (version & 0x0000ff00) >> 8, + (version & 0x000000ff)); + return true; + } + else if (id == cPolicyFile::GetFileHeaderID()) + { + iUserNotify::GetInstance()->Notify(vl, + TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_POL).c_str(), + (version & 0xff000000) >> 24, + (version & 0x00ff0000) >> 16, + (version & 0x0000ff00) >> 8, + (version & 0x000000ff)); + return true; + } + else if (id == cKeyFile::GetFileHeaderID()) + { + iUserNotify::GetInstance()->Notify(vl, + TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_KEY).c_str(), + (version & 0xff000000) >> 24, + (version & 0x00ff0000) >> 16, + (version & 0x0000ff00) >> 8, + (version & 0x000000ff)); + return true; + } + + iUserNotify::GetInstance()->Notify(vl, TSS_GetString(cTWAdmin, twadmin::STR_FILE_TYPE_UNK).c_str()); + return false; +} + +// Calls UserNotify(V_VERBOSE, ...) to print out type of file specified in cFileHeaderID. +// Returns false if encoding not recognized. +// Used in changing and removing encryption algorithms +static bool NotifyEncryptionType(cFileHeader::Encoding encoding, iUserNotify::VerboseLevel vl) +{ + switch (encoding) + { + case cFileHeader::NO_ENCODING: + iUserNotify::GetInstance()->Notify(vl, TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPT_TYPE_NONE).c_str()); + return true; + case cFileHeader::COMPRESSED: + iUserNotify::GetInstance()->Notify(vl, TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPT_TYPE_COMP).c_str()); + return true; + case cFileHeader::ASYM_ENCRYPTION: + iUserNotify::GetInstance()->Notify(vl, TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPT_TYPE_ASYM).c_str()); + return true; + } + + iUserNotify::GetInstance()->Notify(vl, TSS_GetString(cTWAdmin, twadmin::STR_ENCRYPT_TYPE_UNK).c_str()); + return false; +} + diff --git a/src/twadmin/twadmincl.h b/src/twadmin/twadmincl.h new file mode 100644 index 0000000..6386a44 --- /dev/null +++ b/src/twadmin/twadmincl.h @@ -0,0 +1,168 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twadmincl.h -- command line parsing for twadmin +// + +#ifndef __TWADMINCL_H +#define __TWADMINCL_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#include "core/error.h" + +TSS_EXCEPTION( eTWA, eError ) +TSS_EXCEPTION( eTWASkippingDirectory, eTWA ) +TSS_EXCEPTION( eTWAFileNotFound, eTWA ) +TSS_EXCEPTION( eTWAFileAccess, eTWA ) +TSS_EXCEPTION( eTWAFileTypeUnknown, eTWA ) +TSS_EXCEPTION( eTWAInvalidHelpMode, eTWA ) +TSS_EXCEPTION( eTWADecrypt, eTWA ) +TSS_EXCEPTION( eTWADecryptCorrupt, eTWA ) + +TSS_BEGIN_EXCEPTION_NO_CTOR( eTWAEncryptionChange, eTWA ) + eTWAEncryptionChange( const TSTRING& strMsg1, const TSTRING& strMsg2 = _T(""), uint32 flags = 0) + : eTWA( strMsg1 + strMsg2, flags ) {} +TSS_END_EXCEPTION(); + +TSS_BEGIN_EXCEPTION_NO_CTOR( eTWACreateCfgMissingSitekey, eTWA ) + eTWACreateCfgMissingSitekey( const TSTRING& msg, uint32 flags = 0 ); +TSS_END_EXCEPTION(); + +TSS_BEGIN_EXCEPTION_NO_CTOR( eTWACreateCfgSitekeyMismatch, eTWA ) + eTWACreateCfgSitekeyMismatch( const TSTRING& specifiedKeyfile, const TSTRING& configKeyfile, uint32 flags = 0 ) ; +TSS_END_EXCEPTION(); + + +/////////////////////////////////////////////////////////////////////////////// +// cTWAdminCmdLine -- class with a bunch of static member functions helpful in parsing +// the tripwire command line +/////////////////////////////////////////////////////////////////////////////// + +class iTWAMode; + +class cTWAdminCmdLine +{ +public: + //static void InitCmdLineParser(cCmdLineParser& parser); + // call this to initialize the command line parser + + static iTWAMode* GetMode(int argc, const TCHAR *const * argv); + // this will look at the beginning of the command line, determine the appropriate + // mode to create, and returns it. If the mode can't be determined, an error message + // is printed and null is returned. + + // constants for all the command line arguments + enum CmdLineArgs + { + HELP, + + // modes + MODE, // generic -m + MODE_CREATE_CONFIG, + MODE_PRINT_CONFIG, + MODE_CREATE_POLICY, + MODE_PRINT_POLICY, + MODE_REMOVE_ENCRYPTION, + MODE_ENCRYPT, + MODE_EXAMINE, + MODE_GENERATE_KEYS, + MODE_CHANGE_PASSPHRASES, + MODE_HELP, + MODE_HELP_ALL, + MODE_VERSION, + + VERBOSE, + SILENT, + NO_BACKUP, + NO_ENCRYPTION, + + SITE_KEY_FILE, + LOCAL_KEY_FILE, + KEY_FILE, + POL_FILE, + OUTPUT_FILE, + PASSPHRASE, + CFG_FILE, + SITEPASSPHRASE, + LOCALPASSPHRASE, + SITEPASSPHRASEOLD, + LOCALPASSPHRASEOLD, + + PARAMS, // the final params + + NUM_CMDLINEARGS + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// iTWAMode -- base class that contains an interface for initializing tripwire +// in a mode of operation and executing in that mode; a class is derived +// from this for each mode of operation +/////////////////////////////////////////////////////////////////////////////// + +class cCmdLineParser; +class cConfigFile; +class cErrorQueue; + +class iTWAMode +{ +public: + virtual void InitCmdLineParser(cCmdLineParser& cmdLine) = 0; + // fills out the command line parser with all the switches that are appropriate for + // the given mode. + virtual bool Init(const cConfigFile* cf, const cCmdLineParser& cmdLine) = 0; + // call this to ask the mode object to initialize all of its data structures + // with the passed in information. If it returns false, it can be assumed that an error + // message was spit to stderr. + virtual int Execute(cErrorQueue* pQueue) = 0; + // go to work! Returns error level to exit with; 0 implies success + virtual cTWAdminCmdLine::CmdLineArgs GetModeID() const = 0; + // return MODE_* enumeration coresponding to the current mode. + + virtual TSTRING GetModeUsage( void ) = 0; + // return a mode-specific usage string ( a subset of the entire usage statement for + // twadmin + + void SetCfgFilePath( const TSTRING& path ) { mCfgFilePath = path; } + // if the config file is opened in main(), this should be called so the modes know what the path + // to the config file is. + virtual ~iTWAMode() {}; +protected: + TSTRING mCfgFilePath; + +}; + +#endif + diff --git a/src/twadmin/twadminerrors.cpp b/src/twadmin/twadminerrors.cpp new file mode 100644 index 0000000..459f957 --- /dev/null +++ b/src/twadmin/twadminerrors.cpp @@ -0,0 +1,57 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// fcoerrors.cpp +// +// Registers all error strings in the fco package +// + +#include "stdtwadmin.h" +#include "twadminerrors.h" +#include "core/errortable.h" + +#include "twadmincl.h" + +TSS_BEGIN_ERROR_REGISTRATION( twadmin ) + +TSS_REGISTER_ERROR( eTWASkippingDirectory(), _T("Skipping Directory.") ) +TSS_REGISTER_ERROR( eTWAFileNotFound(), _T("File not found.") ) +TSS_REGISTER_ERROR( eTWAFileAccess(), _T("File Access.") ) +TSS_REGISTER_ERROR( eTWAFileTypeUnknown(), _T("File Type Unknown.") ) +TSS_REGISTER_ERROR( eTWAEncryptionChange(), _T("Encryption change.") ) +TSS_REGISTER_ERROR( eTWAInvalidHelpMode(), _T("Invalid mode parameter to help:") ) +TSS_REGISTER_ERROR( eTWADecrypt(), _T("Remove encryption failed.\nFilename: ") ) +TSS_REGISTER_ERROR( eTWADecryptCorrupt(), _T("Remove encryption failed.\nThe file may be corrupt.\nFilename: ") ) +TSS_REGISTER_ERROR( eTWACreateCfgMissingSitekey(), _T("Config file text is missing sitekey.") ) +TSS_REGISTER_ERROR( eTWACreateCfgSitekeyMismatch(), _T("Config file key mismatch.") ) + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/twadmin/twadminerrors.h b/src/twadmin/twadminerrors.h new file mode 100644 index 0000000..ead4837 --- /dev/null +++ b/src/twadmin/twadminerrors.h @@ -0,0 +1,46 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twadminerrors.h +// Date....: 6/2/99 +// Creator.: David Bleckmann (daveb) +// + +#ifndef __TWADMINERRORS_H +#define __TWADMINERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( twadmin ) + +#endif//__FCOERRORS_H + diff --git a/src/twadmin/twadminmain.cpp b/src/twadmin/twadminmain.cpp new file mode 100644 index 0000000..510c785 --- /dev/null +++ b/src/twadmin/twadminmain.cpp @@ -0,0 +1,235 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twadminmain.cpp +// + +#include "stdtwadmin.h" + +#include "core/cmdlineparser.h" +#include "tw/twinit.h" +#include "twadmincl.h" +#include "tw/configfile.h" +#include "tw/twutil.h" +#include "tw/twstrings.h" +#include "twadminstrings.h" +#include "core/timebomb.h" +#include "core/errorbucketimpl.h" +#include "core/archive.h" + +#include "twadmin.h" // for package initialization + +#include + +#if IS_UNIX +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +// terminate and unexpected handlers +// TODO: move these to a common library +/////////////////////////////////////////////////////////////////////////////// +void tw_terminate_handler() +{ + fputs("### Internal Error.\n### Terminate Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +void tw_unexpected_handler() +{ + fputs("### Internal Error.\n### Unexpected Exception Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +int __cdecl _tmain( int argc, const TCHAR* argv[ ], const TCHAR* envp[ ] ) +{ + + + int ret = 0; + + if (TimeBombExploded()) + return 1; + + cTWInit twInit; + + try + { + // set unexpected and terminate handlers + // Note: we do this before Init() in case it attempts to call these handlers + // TODO: move this into the Init() routine + EXCEPTION_NAMESPACE set_terminate(tw_terminate_handler); + EXCEPTION_NAMESPACE set_unexpected(tw_unexpected_handler); + + twInit.Init( argv[0] ); + TSS_Dependency( cTWAdmin ); + + // set up the debug output + cDebug::SetDebugLevel( cDebug::D_DEBUG ); + + + // first, get the right mode... + std::auto_ptr pMode(cTWAdminCmdLine::GetMode(argc, argv)); + if(! pMode.get()) + { + // no valid mode passed; GetMode will display an appropriate string (include usage statement) + ret = 1; + goto exit; + } + + // if version was requested, output version string and exit + if (pMode.get()->GetModeID() == cTWAdminCmdLine::MODE_VERSION) + { + TCOUT << TSS_GetString(cTW, tw::STR_VERSION_LONG) << std::endl; + ret = 0; + goto exit; + } + + // process the command line + cCmdLineParser cmdLine; + pMode->InitCmdLineParser(cmdLine); + + + try + { + cmdLine.Parse(argc, argv); + } + catch( eError& e ) + { + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + + ret = 1; + goto exit; + } + + #if IS_UNIX + // erase the command line + // TODO: it might be a good idea to move this to cTWUtil + int i; + for (i = 1; i < argc; ++i) + memset((char*)argv[i], 0, strlen(argv[i])*sizeof(TCHAR)); + #endif + + cCmdLineIter iter(cmdLine); + if (iter.SeekToArg(cTWAdminCmdLine::HELP)) + { + TCOUT<< TSS_GetString(cTWAdmin, twadmin::STR_TWADMIN_VERSION ) << std::endl; + TCOUT<< TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + //Output a mode specific usage statement + TCOUT<< pMode->GetModeUsage(); + ret = 1; + goto exit; + } + + if (iter.SeekToArg(cTWAdminCmdLine::VERBOSE)) + { + TCERR << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + } + + // open up the config file, possibly using the passed in path + cConfigFile config; + bool configFileOpened = false; + cErrorBucketNull errorNull; // don't spit errors to the user + + if (pMode->GetModeID() != cTWAdminCmdLine::MODE_GENERATE_KEYS && + pMode->GetModeID() != cTWAdminCmdLine::MODE_CHANGE_PASSPHRASES && + pMode->GetModeID() != cTWAdminCmdLine::MODE_CREATE_CONFIG && + pMode->GetModeID() != cTWAdminCmdLine::MODE_PRINT_CONFIG && + pMode->GetModeID() != cTWAdminCmdLine::MODE_HELP) + { + try + { + //open cfg file + TSTRING cfgPath; + cTWUtil::OpenConfigFile( config, cmdLine, cTWAdminCmdLine::CFG_FILE, errorNull, cfgPath); + pMode->SetCfgFilePath( cfgPath ); + configFileOpened = true; + } + catch(eError& error) + { + TSTRING extra; + extra += TSS_GetString(cTW, tw::STR_NEWLINE); + extra += TSS_GetString(cTWAdmin, twadmin::STR_ERR2_CONFIG_OPEN); + cTWUtil::PrintErrorMsg(error, extra); + ret = 1; + goto exit; + } + } + + // ok, now we can initialize the mode object and have it execute + if(! pMode->Init(configFileOpened ? &config : NULL, cmdLine)) + { + TCERR << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + ret = 1; + goto exit; + } + + ret = pMode->Execute(&twInit.errorQueue); + }//end try block + + catch (eError& error) + { + cTWUtil::PrintErrorMsg(error); + ASSERT(false); + ret = 1; + } + + catch (std::bad_alloc e) + { + TCERR << _T("*** Fatal exception: Out of memory "); + TCERR << _T("*** Exiting...\n"); + ret = 1; + } + + catch (std::exception e) + { + TCERR << _T("*** Fatal exception: "); + std::cerr << e.what() << std::endl; + TCERR << _T("*** Exiting...\n"); + ret = 1; + } + + /* + catch (...) + { + TCERR << _T("*** Fatal exception occurred.\n"); + TCERR << _T("*** Exiting...\n"); + ret = 1; + } + */ + +exit: + + + return ret; +} + diff --git a/src/twadmin/twadminstrings.cpp b/src/twadmin/twadminstrings.cpp new file mode 100644 index 0000000..b8c1a0a --- /dev/null +++ b/src/twadmin/twadminstrings.cpp @@ -0,0 +1,298 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twadminstrings.cpp +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwadmin.h" +#include "twadmin.h" +#include "twadminstrings.h" + +TSS_BeginStringtable( cTWAdmin ) + + TSS_StringEntry( twadmin::STR_TWADMIN_VERSION, _T("twadmin: Tripwire administrative tool.\n") ), + + TSS_StringEntry( twadmin::STR_TWADMIN_USAGE_SUMMARY, + _T("Usage:\n") + _T("\n") + _T("Create Configuration File: twadmin [-m F|--create-cfgfile][options] cfgfile.txt\n") + _T("Print Configuration File: twadmin [-m f|--print-cfgfile] [options]\n") + _T("Create Policy File: twadmin [-m P|--create-polfile] [options] polfile.txt\n") + _T("Print Policy File: twadmin [-m p|--print-polfile] [options]\n") + _T("Remove Encryption: twadmin [-m R|--remove-encryption] [options] [file1...]\n") + _T("Encryption: twadmin [-m E|--encrypt] [options] [file1...]\n") + _T("Examine Encryption: twadmin [-m e|--examine] [options] [file1...]\n") + _T("Generate Keys: twadmin [-m G|--generate-keys] [options]\n") + _T("Change Passphrases: twadmin [-m C|--change-passphrases] [options]\n") + _T("\n") + _T("Type 'twadmin [mode] --help' OR\n") + _T("'twadmin --help mode [mode...]' OR\n") + _T("'twadmin --help all' for extended help\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_CREATE_CFGFILE, + _T("Create Configuration File mode:\n") + _T(" -m F --create-cfgfile\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T(" -e --no-encryption\n") + _T("configfile.txt\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("Exactly one of -e or -S must be specified.\n") + _T("The -Q option is valid only with -S.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_PRINT_CFGFILE, + _T("Print Configuration File mode:\n") + _T(" -m f --print-cfgfile\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_CREATE_POLFILE, + _T("Replace Policy File mode:\n") + _T(" -m P --create-polfile\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T(" -e --no-encryption\n") + _T("policyfile.txt\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("The -e and -S options are mutually exclusive.\n") + _T("The -e and -Q options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_PRINT_POLFILE, + _T("Print Policy File mode:\n") + _T(" -m p --print-polfile\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -p polfile --polfile polfile\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_REMOVE_ENCRYPTION, + _T("Remove Encryption mode:\n") + _T(" -m R --remove-encryption\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T("file1 [file2 ...]\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_ENCRYPT, + _T("Encryption mode:\n") + _T(" -m E --encrypt\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T("file1 [file2 ...]\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_EXAMINE, + _T("Examine Encryption mode:\n") + _T(" -m e --examine\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T("file1 [file2 ...]\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_GENERATE_KEYS, + _T("Generate Keys mode:\n") + _T(" -m G --generate-keys\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("Exactly one of -S or -L must be specified.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_TWADMIN_HELP_CHANGE_PASSPHRASES, + _T("Change Passphrases mode:\n") + _T(" -m C --change-passphrases\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -S sitekey --site-keyfile sitekey\n") + _T(" -P passphrase --local-passphrase passphrase\n") + _T(" -Q passphrase --site-passphrase passphrase\n") + _T(" --local-passphrase-old passphrase-old\n") + _T(" --site-passphrase-old passphrase-old\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("At least one of -S or -L must be specified.\n") + _T("\n") + ), + + TSS_StringEntry( twadmin::STR_KEYGEN_VERBOSE_OUTPUT_FILES, _T("Using site keyfile: \"%s\" and local keyfile: \"%s\"\n") ), + TSS_StringEntry( twadmin::STR_KEYGEN_VERBOSE_PASSPHRASES, _T("Using supplied passphrases.\n") ), + TSS_StringEntry( twadmin::STR_KEYGEN_VERBOSE_SITEKEY, _T("Generating site key: %s\n") ), + TSS_StringEntry( twadmin::STR_KEYGEN_VERBOSE_LOCALKEY, _T("Generating local key: %s\n") ), + TSS_StringEntry( twadmin::STR_UPCONFIG_VERBOSE_PT_CONFIG, _T("Using plaintext config file: %s\n") ), + TSS_StringEntry( twadmin::STR_UPCONFIG_CREATING_CONFIG, _T("Writing configuration file: %s\n") ), + TSS_StringEntry( twadmin::STR_UPCONFIG_VERBOSE_PT_POLICY, _T("Using plaintext policy file: %s\n") ), + TSS_StringEntry( twadmin::STR_GENERATING_KEYS, _T("Generating key (this may take several minutes)...") ), + TSS_StringEntry( twadmin::STR_GENERATION_COMPLETE, _T("Key generation complete.\n") ), + TSS_StringEntry( twadmin::STR_SITEKEYFILE, _T("\tSite Keyfile: ") ), + TSS_StringEntry( twadmin::STR_LOCALKEYFILE, _T("\tLocal Keyfile: ") ), + TSS_StringEntry( twadmin::STR_SITEKEY_EXISTS_1, _T("The site key file: \"") ), + TSS_StringEntry( twadmin::STR_SITEKEY_EXISTS_2, _T("\" exists. Overwrite (Y/N)? ") ), + TSS_StringEntry( twadmin::STR_LOCALKEY_EXISTS_1, _T("The local key file: \"") ), + TSS_StringEntry( twadmin::STR_LOCALKEY_EXISTS_2, _T("\" exists. Overwrite (Y/N)? ") ), + TSS_StringEntry( twadmin::STR_KEYFILE_BACKED_UP_AS, _T("Keyfile backed up as %s\n") ), + TSS_StringEntry( twadmin::STR_CONVERTING_FILES, _T("Converting files.\n") ), + TSS_StringEntry( twadmin::STR_EXAMINING_FILE, _T("Examining file: ") ), + TSS_StringEntry( twadmin::STR_KEYS_DECRYPT, _T("The following keys decrypt this file: ") ), + TSS_StringEntry( twadmin::STR_BACKUP_EXISTS_1, _T("Backup file ") ), + TSS_StringEntry( twadmin::STR_BACKUP_EXISTS_2, _T(" exists. Overwrite (Y/N)? ") ), + TSS_StringEntry( twadmin::STR_PASSPHRASE_HINT, _T("\n(When selecting a passphrase, keep in mind that good passphrases typically\n") + _T("have upper and lower case letters, digits and punctuation marks, and are\n") + _T("at least 8 characters in length.)\n\n") + ), + TSS_StringEntry( twadmin::STR_POL_NOT_UPDATED, _T("The policy file was not altered.\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPT_TYPE_NONE, _T("Encoding: None\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPT_TYPE_COMP, _T("Encoding: Compressed\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPT_TYPE_ASYM, _T("Encoding: Asymmetric Encryption\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPT_TYPE_UNK, _T("Encoding: Unrecognized\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_DB, _T("File Type: Tripwire Database (Ver %X.%X.%X.%X)\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_REP, _T("File Type: Tripwire Report (Ver %X.%X.%X.%X)\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_CFG, _T("File Type: Tripwire Config File (Ver %X.%X.%X.%X)\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_POL, _T("File Type: Tripwire Policy File (Ver %X.%X.%X.%X)\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_KEY, _T("File Type: Tripwire Key File (Ver %X.%X.%X.%X)\n") ), + TSS_StringEntry( twadmin::STR_FILE_TYPE_UNK, _T("File Type: Unknown\n") ), + TSS_StringEntry( twadmin::STR_ENTER_SITE_PASS, _T("Enter the site keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_VERIFY_SITE_PASS, _T("Verify the site keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_ENTER_LOCAL_PASS, _T("Enter the local keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_VERIFY_LOCAL_PASS, _T("Verify the local keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_ENTER_SITE_PASS_OLD, _T("Enter the old site keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_ENTER_LOCAL_PASS_OLD, _T("Enter the old local keyfile passphrase:") ), + TSS_StringEntry( twadmin::STR_REMOVE_ENCRYPTION_WARNING, _T("NOTE: Removing encryption on a file leaves it open to tampering!\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPTION_REMOVED, _T("Encryption removed from \"%s\" successfully.\n") ), + TSS_StringEntry( twadmin::STR_ENCRYPTION_SUCCEEDED, _T("\"%s\" encrypted successfully.\n") ), + TSS_StringEntry( twadmin::STR_FILE, _T("File: \"") ), + TSS_StringEntry( twadmin::STR_ENDQUOTE_NEWLINE, _T("\"\n") ), + + TSS_StringEntry( twadmin::STR_ERR2_NO_PT_CONFIG, _T("No plaintext config file specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_NO_CONFIG, _T("No config file specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_NO_PT_POLICY, _T("No plaintext policy file specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_NO_POLICY, _T("No policy file specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_CONFIG_OPEN, _T("Config file could not be opened.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_SITE_KEY_NOENCRYPT_NOT_SPECIFIED, _T("Site key file or no-encryption must be specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_LOCAL_KEY_NOT_SPECIFIED, _T("Local key file must be specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_KEYS_NOT_SPECIFIED, _T("Site or local key file must be specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_KEY_FILENAMES_IDENTICAL, _T("Site and local key filenames may not be identical.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_SITE_KEY_DOESNT_EXIST, _T("Site key does not exist. Use -m G mode to generate a new key.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_SITE_KEY_READ_ONLY, _T("Site key is read only, cannot overwrite.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_LOCAL_KEY_DOESNT_EXIST, _T("Local key does not exist. Use -m G mode to generate a new key.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_LOCAL_KEY_READ_ONLY, _T("Local key is read only, cannot overwrite.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_COULDNT_RENAME_FILE, _T("File could not be renamed ") ), + TSS_StringEntry( twadmin::STR_ERR2_CONVERSION_FILE_READ_ONLY1, _T("File to be converted ") ), + TSS_StringEntry( twadmin::STR_ERR2_CONVERSION_FILE_READ_ONLY2, _T(" is Read Only, key change aborted.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_UNABLE_TO_PRINT_POLICY, _T("\nUnable to print policy file.") ), + TSS_StringEntry( twadmin::STR_ERR2_CAN_NOT_ENCRYPT_KEYFILE, _T("Can not encrypt a keyfile.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_CAN_NOT_DECRYPT_KEYFILE, _T("Can not remove encryption on a keyfile.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_NO_FILES_SPECIFIED, _T("No files specified.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_LONE_SITE_PASSPHRASE, _T("Site passphrase was specified without corresponding site keyfile.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_LONE_LOCAL_PASSPHRASE, _T("Local passphrase was specified without corresponding local keyfile.\n") ), + + TSS_StringEntry( twadmin::STR_ERR2_FILE_DOES_NOT_EXIST, _T("File does not exist.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_COULD_NOT_BE_OPENED, _T("File could not be opened.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_COULD_NOT_BE_READ, _T("File could not be read.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_NOT_A_TW_FILE, _T("File is not a Tripwire data file.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_COULD_NOT_BE_EXAMINED,_T("File could not be examined.\n") ), + + //TSS_StringEntry( twadmin::STR_ERR2_FILE_TYPE_UNKNOWN, _T("Error: File type is unknown for file %s\n") ), + TSS_StringEntry( twadmin::STR_ERR2_ENCODING_TYPE_UNKNOWN, _T("Encoding type is unknown.") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_NOT_ENCRYPED, _T("This file is not encrypted, decryption skipped.\nFilename: ") ), + TSS_StringEntry( twadmin::STR_ERR2_REMOVE_ENCRYPTION_FAILED, _T("Encryption removal failed.\nFilename: ") ), + TSS_StringEntry( twadmin::STR_ERR2_COULD_NOT_OPEN_PROVIDED_KEYFILE, _T("Error: Provided keyfile could not be opened ") ), + TSS_StringEntry( twadmin::STR_ERR2_FILE_ALREADY_ENCRYPTED, _T("File is currently encrypted. Skipping.\n") ), + TSS_StringEntry( twadmin::STR_ERR2_ENCRYPTION_FAILED, _T("Encryption failed.\n") ), + + // keygeneration + TSS_StringEntry( twadmin::STR_ERR2_KEYGEN_FILEWRITE, _T("Error: File could not be written to: ") ), + TSS_StringEntry( twadmin::STR_ERR2_KEYGEN, _T("Error generating key, ") ), + TSS_StringEntry( twadmin::STR_ERR2_KEYGEN2, _T(" not written.") ), + TSS_StringEntry( twadmin::STR_ERR2_PASSPHRASE_NOKEY, _T("Error: A passphrase has been specified without the corresponding key.") ), + + TSS_StringEntry( twadmin::STR_ERR2_CREATE_CFG_MISSING_KEYFILE, _T("A config file can not be created and encrypted with a keyfile unless the same keyfile is specified as the SITEKEYFILE within the new config file text.") ), + TSS_StringEntry( twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH1, _T("The specified keyfile \"") ), + TSS_StringEntry( twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH2, _T("\" does not match the keyfile specified in the new config file text \"") ), + TSS_StringEntry( twadmin::STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH3, _T("\".") ), + +TSS_EndStringtable( cTWAdmin ) + diff --git a/src/twadmin/twadminstrings.h b/src/twadmin/twadminstrings.h new file mode 100644 index 0000000..12915f5 --- /dev/null +++ b/src/twadmin/twadminstrings.h @@ -0,0 +1,159 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twadminstrings.h +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#ifndef __TWADMINSTRINGS_H +#define __TWADMINSTRINGS_H + +#include "twadmin.h" // for: STRINGTABLE syntax + +//--Message Keys + +TSS_BeginStringIds( twadmin ) + + STR_TWADMIN_VERSION, + STR_TWADMIN_USAGE_SUMMARY, + STR_TWADMIN_HELP_CREATE_CFGFILE, + STR_TWADMIN_HELP_PRINT_CFGFILE, + STR_TWADMIN_HELP_CREATE_POLFILE, + STR_TWADMIN_HELP_PRINT_POLFILE, + STR_TWADMIN_HELP_REMOVE_ENCRYPTION, + STR_TWADMIN_HELP_ENCRYPT, + STR_TWADMIN_HELP_EXAMINE, + STR_TWADMIN_HELP_GENERATE_KEYS, + STR_TWADMIN_HELP_CHANGE_PASSPHRASES, + STR_KEYGEN_VERBOSE_OUTPUT_FILES, + STR_KEYGEN_VERBOSE_PASSPHRASES, + STR_KEYGEN_VERBOSE_SITEKEY, + STR_KEYGEN_VERBOSE_LOCALKEY, + STR_UPCONFIG_VERBOSE_PT_CONFIG, + STR_UPCONFIG_CREATING_CONFIG, + STR_UPCONFIG_VERBOSE_PT_POLICY, + STR_SITEKEYFILE, + STR_LOCALKEYFILE, + STR_SITEKEY_EXISTS_1, + STR_SITEKEY_EXISTS_2, + STR_LOCALKEY_EXISTS_1, + STR_LOCALKEY_EXISTS_2, + STR_KEYFILE_BACKED_UP_AS, + STR_CONVERTING_FILES, + STR_EXAMINING_FILE, + STR_KEYS_DECRYPT, + STR_BACKUP_EXISTS_1, + STR_BACKUP_EXISTS_2, + STR_PASSPHRASE_HINT, + STR_POL_NOT_UPDATED, + STR_ENCRYPT_TYPE_NONE, + STR_ENCRYPT_TYPE_COMP, + STR_ENCRYPT_TYPE_ASYM, + STR_ENCRYPT_TYPE_UNK, + STR_FILE_TYPE_DB, + STR_FILE_TYPE_REP, + STR_FILE_TYPE_CFG, + STR_FILE_TYPE_POL, + STR_FILE_TYPE_KEY, + STR_FILE_TYPE_UNK, + STR_ENTER_SITE_PASS, + STR_VERIFY_SITE_PASS, + STR_ENTER_LOCAL_PASS, + STR_VERIFY_LOCAL_PASS, + STR_ENTER_SITE_PASS_OLD, + STR_ENTER_LOCAL_PASS_OLD, + STR_REMOVE_ENCRYPTION_WARNING, + STR_ENCRYPTION_REMOVED, + STR_ENCRYPTION_SUCCEEDED, + STR_FILE, + STR_ENDQUOTE_NEWLINE, + + // key generation + STR_GENERATING_KEYS, + STR_GENERATION_COMPLETE, + + // Extra error strings + STR_ERR2_NO_PT_CONFIG, + STR_ERR2_NO_CONFIG, + STR_ERR2_NO_PT_POLICY, + STR_ERR2_NO_POLICY, + STR_ERR2_CONFIG_OPEN, + STR_ERR2_SITE_KEY_NOENCRYPT_NOT_SPECIFIED, + STR_ERR2_LOCAL_KEY_NOT_SPECIFIED, + STR_ERR2_KEYS_NOT_SPECIFIED, + STR_ERR2_KEY_FILENAMES_IDENTICAL, + STR_ERR2_SITE_KEY_DOESNT_EXIST, + STR_ERR2_SITE_KEY_READ_ONLY, + STR_ERR2_LOCAL_KEY_DOESNT_EXIST, + STR_ERR2_LOCAL_KEY_READ_ONLY, + STR_ERR2_COULDNT_RENAME_FILE, + STR_ERR2_CONVERSION_FILE_READ_ONLY1, + STR_ERR2_CONVERSION_FILE_READ_ONLY2, + STR_ERR2_UNABLE_TO_PRINT_POLICY, + STR_ERR2_CAN_NOT_ENCRYPT_KEYFILE, + STR_ERR2_CAN_NOT_DECRYPT_KEYFILE, + STR_ERR2_NO_FILES_SPECIFIED, + STR_ERR2_LONE_SITE_PASSPHRASE, + STR_ERR2_LONE_LOCAL_PASSPHRASE, + + STR_ERR2_FILE_DOES_NOT_EXIST, + STR_ERR2_FILE_COULD_NOT_BE_OPENED, + STR_ERR2_FILE_COULD_NOT_BE_READ, + STR_ERR2_FILE_NOT_A_TW_FILE, + STR_ERR2_FILE_COULD_NOT_BE_EXAMINED, + + //now a ERR1 str STR_ERR2_FILE_TYPE_UNKNOWN, + STR_ERR2_ENCODING_TYPE_UNKNOWN, + STR_ERR2_FILE_NOT_ENCRYPED, + //STR_ERR2_REMOVE_ENCRYPTION_WARNING, + STR_ERR2_REMOVE_ENCRYPTION_FAILED, + //STR_ERR2_ENCRYPTION_REMOVED, + STR_ERR2_COULD_NOT_OPEN_PROVIDED_KEYFILE, + STR_ERR2_FILE_ALREADY_ENCRYPTED, + STR_ERR2_ENCRYPTION_FAILED, + + // keygeneration + STR_ERR2_KEYGEN_FILEWRITE, + STR_ERR2_KEYGEN, + STR_ERR2_KEYGEN2, + STR_ERR2_PASSPHRASE_NOKEY, + + STR_ERR2_CREATE_CFG_MISSING_KEYFILE, + STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH1, + STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH2, + STR_ERR2_CREATE_CFG_SITEKEY_MISMATCH3 + +TSS_EndStringIds( twadmin ) + +#endif//__TWADMINSTRINGS_H + diff --git a/src/twcrypto/Makefile.am b/src/twcrypto/Makefile.am new file mode 100644 index 0000000..7685ffd --- /dev/null +++ b/src/twcrypto/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libtwcrypto.a +libtwcrypto_a_SOURCES = \ + bytequeue.cpp crypto.cpp cryptoarchive.cpp keyfile.cpp \ + stdtwcrypto.cpp twcrypto.cpp twcryptoerrors.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtwcrypto_a_OBJECTS) diff --git a/src/twcrypto/Makefile.in b/src/twcrypto/Makefile.in new file mode 100644 index 0000000..86ca201 --- /dev/null +++ b/src/twcrypto/Makefile.in @@ -0,0 +1,400 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libtwcrypto_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/twcrypto +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libtwcrypto_a_AR = $(AR) $(ARFLAGS) +libtwcrypto_a_LIBADD = +am_libtwcrypto_a_OBJECTS = bytequeue.$(OBJEXT) crypto.$(OBJEXT) \ + cryptoarchive.$(OBJEXT) keyfile.$(OBJEXT) \ + stdtwcrypto.$(OBJEXT) twcrypto.$(OBJEXT) \ + twcryptoerrors.$(OBJEXT) +libtwcrypto_a_OBJECTS = $(am_libtwcrypto_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libtwcrypto_a_SOURCES) +DIST_SOURCES = $(libtwcrypto_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libtwcrypto.a +libtwcrypto_a_SOURCES = \ + bytequeue.cpp crypto.cpp cryptoarchive.cpp keyfile.cpp \ + stdtwcrypto.cpp twcrypto.cpp twcryptoerrors.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/twcrypto/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/twcrypto/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libtwcrypto.a: $(libtwcrypto_a_OBJECTS) $(libtwcrypto_a_DEPENDENCIES) + -rm -f libtwcrypto.a + $(libtwcrypto_a_AR) libtwcrypto.a $(libtwcrypto_a_OBJECTS) $(libtwcrypto_a_LIBADD) + $(RANLIB) libtwcrypto.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtwcrypto_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/twcrypto/bytequeue.cpp b/src/twcrypto/bytequeue.cpp new file mode 100644 index 0000000..0f3213e --- /dev/null +++ b/src/twcrypto/bytequeue.cpp @@ -0,0 +1,333 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// bytequeue.cpp - written and placed in the public domain by Wei Dai +// - modified 29 Oct 1998 mdb + +#include "stdtwcrypto.h" + +#include "bytequeue.h" +#include "cryptlib/queue.h" +#include "cryptlib/misc.h" + +//----------------------------------------------------------------------------- +// cByteQueueNode +// this class for use by cByteQueue only +//----------------------------------------------------------------------------- +class cByteQueueNode +{ +public: + cByteQueueNode(unsigned int maxSize); + + unsigned int CurrentSize() const + {return tail-head;} + unsigned int UsedUp() const + {return (head==MaxSize());} + + unsigned int Put(byte inByte); + unsigned int Put(const byte *inString, unsigned int length); + + unsigned int Get(byte &outByte); + unsigned int Get(byte *outString, unsigned int getMax); + + unsigned int Peek(byte &outByte) const; + + void CopyTo(BufferedTransformation &target) const + {target.Put(buf+head, tail-head);} + void CopyTo(byte *target) const + {memcpy(target, buf+head, tail-head);} + + byte operator[](unsigned int i) const + {return buf[i-head];} + + cByteQueueNode *next; + +private: + unsigned int MaxSize() const {return buf.size;} + + SecByteBlock buf; + unsigned int head, tail; +}; + + +cByteQueueNode::cByteQueueNode(unsigned int maxSize) + : buf(maxSize) +{ + head = tail = 0; + next = 0; +} + +unsigned int cByteQueueNode::Put(byte inByte) +{ + if (MaxSize()==tail) + return 0; + + buf[tail++]=inByte; + return 1; +} + +unsigned int cByteQueueNode::Put(const byte *inString, unsigned int length) +{ + unsigned int l = STDMIN(length, MaxSize()-tail); + memcpy(buf+tail, inString, l); + tail += l; + return l; +} + +unsigned int cByteQueueNode::Get(byte &outByte) +{ + if (tail==head) + return 0; + + outByte=buf[head++]; + return 1; +} + +unsigned int cByteQueueNode::Get(byte *outString, unsigned int getMax) +{ + unsigned int l = STDMIN(getMax, tail-head); + memcpy(outString, buf+head, l); + head += l; + return l; +} + +unsigned int cByteQueueNode::Peek(byte &outByte) const +{ + if (tail==head) + return 0; + + outByte=buf[head]; + return 1; +} + +//----------------------------------------------------------------------------- +// cByteQueue +//----------------------------------------------------------------------------- + +cByteQueue::cByteQueue(int mNodeSize) + : mNodeSize(mNodeSize), + mCurrentSize(0) +{ + head = tail = new cByteQueueNode(mNodeSize); +} + +cByteQueue::cByteQueue(const cByteQueue ©) +{ + CopyFrom(copy); +} + +void cByteQueue::CopyFrom(const cByteQueue ©) +{ + mNodeSize = copy.mNodeSize; + mCurrentSize = copy.mCurrentSize; + + head = tail = new cByteQueueNode(*copy.head); + + for (cByteQueueNode *current=copy.head->next; current; current=current->next) + { + tail->next = new cByteQueueNode(*current); + tail = tail->next; + } + + tail->next = NULL; +} + +cByteQueue::~cByteQueue() +{ + Destroy(); +} + +void cByteQueue::Destroy() +{ + cByteQueueNode *next; + + for (cByteQueueNode *current=head; current; current=next) + { + next=current->next; + delete current; + } + + mCurrentSize = 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// CopyTo -- note that this does not remove anything from the queue +/////////////////////////////////////////////////////////////////////////////// +void cByteQueue::CopyTo(BufferedTransformation &target) const +{ + for (cByteQueueNode *current=head; current; current=current->next) + current->CopyTo(target); +} + +void cByteQueue::CopyTo(byte *target) const +{ + for (cByteQueueNode *current=head; current; current=current->next) + { + current->CopyTo(target); + target += current->CurrentSize(); + } +} + +unsigned long cByteQueue::CurrentSize() const +{ + return mCurrentSize; + /* + unsigned long size=0; + + for (cByteQueueNode *current=head; current; current=current->next) + size += current->CurrentSize(); + + return size; + */ +} + +void cByteQueue::Put(byte inByte) +{ + if (!tail->Put(inByte)) + { + tail->next = new cByteQueueNode(mNodeSize); + tail = tail->next; + tail->Put(inByte); + } + // put increases the size of the queue by one + mCurrentSize++; +} + +void cByteQueue::Put(const byte *inString, unsigned int length) +{ + unsigned int l; + + // put increases the size of the queue by length + mCurrentSize += length; + + while ((l=tail->Put(inString, length)) < length) + { + tail->next = new cByteQueueNode(mNodeSize); + tail = tail->next; + inString += l; + length -= l; + } +} + +unsigned int cByteQueue::Get(byte &outByte) +{ + int l = head->Get(outByte); + if (head->UsedUp()) + { + cByteQueueNode *temp=head; + head = head->next; + delete temp; + if (!head) // just deleted the last node + head = tail = new cByteQueueNode(mNodeSize); + } + // put decreases the size of the queue by one + mCurrentSize--; + + return l; +} + +unsigned int cByteQueue::Get(byte *outString, unsigned int getMax) +{ + unsigned int getMaxSave=getMax; + cByteQueueNode *current=head; + + while (getMax && current) + { + int l=current->Get(outString, getMax); + + outString += l; + getMax -= l; + + current = current->next; + } + + // delete all used up nodes except the last one, to avoid the final new + // that used to be below.... + while (head && head->UsedUp() && (head != tail)) + { + current=head; + head=head->next; + delete current; + } + + /* + if (!head) // every single node has been used up and deleted + head = tail = new cByteQueueNode(mNodeSize); + */ + + int rtn = getMaxSave-getMax; + mCurrentSize -= rtn; + + return (rtn); +} + +unsigned int cByteQueue::Peek(byte &outByte) const +{ + return head->Peek(outByte); +} + +cByteQueue & cByteQueue::operator=(const cByteQueue &rhs) +{ + Destroy(); + CopyFrom(rhs); + return *this; +} + +bool cByteQueue::operator==(const cByteQueue &rhs) const +{ + const unsigned long currentSize = CurrentSize(); + + if (currentSize != rhs.CurrentSize()) + return false; + + for (unsigned long i = 0; inext) + { + if (i < current->CurrentSize()) + return (*current)[i]; + + i -= current->CurrentSize(); + } + + // i should be less than CurrentSize(), therefore we should not be here + assert(false); + return 0; +} + diff --git a/src/twcrypto/bytequeue.h b/src/twcrypto/bytequeue.h new file mode 100644 index 0000000..a1056de --- /dev/null +++ b/src/twcrypto/bytequeue.h @@ -0,0 +1,83 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// bytequeue.h +// +// cByteQueue -- specification file for an unlimited queue for storing bytes +// +// this is a superior implementation of the byte queue supplied with the crypto++ lib +#ifndef __BYTEQUEUE_H +#define __BYTEQUEUE_H + +#include "cryptlib/cryptlib.h" + +class cByteQueueNode; + +class cByteQueue : public BufferedTransformation +{ +public: + cByteQueue(int nodeSize=1024); + cByteQueue(const cByteQueue ©); + ~cByteQueue(); + + // how many bytes currently stored + unsigned long CurrentSize() const; + unsigned long MaxRetrieveable() + {return CurrentSize();} + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + + // both functions returns the number of bytes actually retrived + unsigned int Get(byte &outByte); + unsigned int Get(byte *outString, unsigned int getMax); + + unsigned int Peek(byte &outByte) const; + + void CopyTo(BufferedTransformation &target) const; + void CopyTo(byte *target) const; + + cByteQueue & operator=(const cByteQueue &rhs); + bool operator==(const cByteQueue &rhs) const; + byte operator[](unsigned long i) const; + +private: + void CopyFrom(const cByteQueue ©); + void Destroy(); + + int mNodeSize; + int mCurrentSize; + cByteQueueNode *head, *tail; +}; + +#endif //__BYTEQUEUE_H + diff --git a/src/twcrypto/crypto.cpp b/src/twcrypto/crypto.cpp new file mode 100644 index 0000000..5b02903 --- /dev/null +++ b/src/twcrypto/crypto.cpp @@ -0,0 +1,1271 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// crypto.cpp -- Tripwire crypto implementation +// + +#include "stdtwcrypto.h" + +#include "crypto.h" +#include "core/errorgeneral.h" +#include "time.h" +#include "core/archive.h" + +#include "cryptlib/sha.h" +#include "cryptlib/rng.h" +#include "cryptlib/des.h" +#include "cryptlib/integer.h" +#include "cryptlib/elgamal.h" +#include "cryptlib/des.h" +#ifdef _IDEA_ENCRYPTION +#include "cryptlib/idea.h" +#endif +#ifdef _RSA_ENCRYPTION +#include "cryptlib/rsa.h" +#endif + +const uint32 EL_GAMAL_SIG_PUBLIC_MAGIC_NUM = 0x7ae2c945; +const uint32 EL_GAMAL_SIG_PRIVATE_MAGIC_NUM = 0x0d0ffa12; + +/////////////////////////////////////////////////////////////////////////////// +// macros for reading and writing integers + +#define WRITE_INTEGER(I) \ + len = I.MinEncodedSize(Integer::UNSIGNED); \ + ASSERT(len >=0 && len < 9000); \ + i32 = tw_htonl(len); \ + memcpy(pOut, &i32, sizeof(i32)); \ + pOut += sizeof(int32); \ + I.Encode(pOut, len, Integer::UNSIGNED); \ + pOut += len; + +#define READ_INTEGER(I) \ + memcpy(&i32, pIn, sizeof(i32)); \ + len = tw_ntohl(i32); \ + ASSERT(len >= 0 && len < 9000); \ + pIn += sizeof(int32); \ + I.Decode(pIn, len, Integer::UNSIGNED); \ + pIn += len; + +/////////////////////////////////////////////////////////////////////////////// +// class cNullCipher -- no encryption cipher + +int cNullCipher::GetBlockSizePlain() +{ + // lets use the blocksize of TripleDES_Encryption since that may be + // better than picking a blocksize at random + return TripleDES_Encryption::BLOCKSIZE; +} + +// return the size of data blocks for plaintext and cipertext +int cNullCipher::GetBlockSizeCipher() +{ + return TripleDES_Encryption::BLOCKSIZE; +} + +// process a block of data. indata and outdata may be the same memory +void cNullCipher::ProcessBlock(const void* indata, void* outdata) +{ + memmove(outdata, indata, TripleDES_Encryption::BLOCKSIZE); +} + +////////////////////////////////////////////////////////////////////////////// +// class cIDEA +////////////////////////////////////////////////////////////////////////////// + +#ifdef _IDEA_ENCRYPTION + +class cIDEA_i +{ +public: + IDEA* mpIDEA; +}; + +cIDEA::cIDEA() +{ + mpData = new cIDEA_i; + + mpData->mpIDEA = 0; +} + +cIDEA::~cIDEA() +{ + delete mpData->mpIDEA; + delete mpData; + mpData = 0; +} + +void cIDEA::SetKey(iCipher::EncryptionDir dir, const cHashedKey128& key) +{ + // some things we are assuming + ASSERT(IDEA::KEYLENGTH == 16); + ASSERT(mpData); + + delete mpData->mpIDEA; + mpData->mpIDEA = new IDEA((byte*)key.GetKey(), dir == iCipher::ENCRYPT ? ENCRYPTION : DECRYPTION); +} + +// return the size of data block this crypter works on +int cIDEA::GetBlockSizePlain() +{ + return IDEA::BLOCKSIZE; +} + +int cIDEA::GetBlockSizeCipher() +{ + return IDEA::BLOCKSIZE; +} + +// process a block of data. indata and outdata may be the same memory +void cIDEA::ProcessBlock(const void* indata, void* outdata) +{ + ASSERT(mpData->mpIDEA); + + if (!mpData->mpIDEA) + { + ThrowAndAssert(eInternal(_T("Key not set in symmetric encryption."))); + } + + mpData->mpIDEA->ProcessBlock((byte*)indata, (byte*)outdata); +} + +#endif // _IDEA_ENCRYPTION + +////////////////////////////////////////////////////////////////////////////// +// class cTripleDES +////////////////////////////////////////////////////////////////////////////// + +class cTripleDES_i +{ +public: + TripleDES_Encryption* mpEncryptor; + TripleDES_Decryption* mpDecryptor; +}; + +cTripleDES::cTripleDES() +{ + mpData = new cTripleDES_i; + + mpData->mpEncryptor = 0; + mpData->mpDecryptor = 0; +} + +cTripleDES::~cTripleDES() +{ + delete mpData->mpEncryptor; + delete mpData->mpDecryptor; + delete mpData; + mpData = 0; +} + +void cTripleDES::SetKey(iCipher::EncryptionDir dir, const cHashedKey192& key) +{ + // some things we are assuming + ASSERT(TripleDES_Encryption::KEYLENGTH == 24); + ASSERT(cHashedKey192::GetWriteLen() == 24); + ASSERT(mpData != 0); + + if (dir == iCipher::ENCRYPT) + { + delete mpData->mpEncryptor; + delete mpData->mpDecryptor; + mpData->mpDecryptor = 0; + mpData->mpEncryptor = new TripleDES_Encryption((byte*)key.GetKey()); + } + else + { + delete mpData->mpEncryptor; + delete mpData->mpDecryptor; + mpData->mpEncryptor = 0; + mpData->mpDecryptor = new TripleDES_Decryption((byte*)key.GetKey()); + } +} + +// return the size of data block this crypter works on +int cTripleDES::GetBlockSizePlain() +{ + ASSERT(TripleDES_Encryption::BLOCKSIZE == TripleDES_Decryption::BLOCKSIZE); + return TripleDES_Encryption::BLOCKSIZE; +} + +int cTripleDES::GetBlockSizeCipher() +{ + ASSERT(TripleDES_Encryption::BLOCKSIZE == TripleDES_Decryption::BLOCKSIZE); + return TripleDES_Encryption::BLOCKSIZE; +} + +// process a block of data. indata and outdata may be the same memory +void cTripleDES::ProcessBlock(const void* indata, void* outdata) +{ + ASSERT(mpData != 0); + ASSERT(mpData->mpEncryptor || mpData->mpDecryptor); + + if (!mpData->mpEncryptor && !mpData->mpDecryptor) + { + ThrowAndAssert(INTERNAL_ERROR("crypto.cpp")); //cTWError::E_INTERNAL, TSTRING(_T("Key not set in symmetric encryption.")))); + } + + if (mpData->mpEncryptor) + mpData->mpEncryptor->ProcessBlock((byte*)indata, (byte*)outdata); + else + mpData->mpDecryptor->ProcessBlock((byte*)indata, (byte*)outdata); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cRSA + +#ifdef _RSA_ENCRYPTION + +// class cRSAPrivateKey + +class cRSAPrivateKey_i +{ +public: + int16 mKeyLength; + RSAPrivateKey* mpKey; +}; + +cRSAPrivateKey::cRSAPrivateKey() +{ + mpData = new cRSAPrivateKey_i; + mpData->mpKey = 0; + mpData->mKeyLength = 0; +} + +cRSAPrivateKey::cRSAPrivateKey(void* pDataStream) +{ + mpData = new cRSAPrivateKey_i; + + int32 len; + int32 i32; + int16 i16; + + byte* pIn = (byte*)pDataStream; + + memcpy(&i16, pIn, sizeof(i16)); + mpData->mKeyLength = tw_ntohs(i16); + pIn += sizeof(int16); + + Integer n, e, d, p, q, dp, dq, u; + + READ_INTEGER(n); + READ_INTEGER(e); + READ_INTEGER(d); + READ_INTEGER(p); + READ_INTEGER(q); + READ_INTEGER(dp); + READ_INTEGER(dq); + READ_INTEGER(u); + + mpData->mpKey = new RSAPrivateKey(n, e, d, p, q, dp, dq, u); +} + +cRSAPrivateKey::~cRSAPrivateKey() +{ + if (mpData) + { + delete mpData->mpKey; + delete mpData; + } +} + +int cRSAPrivateKey::GetWriteLen() const +{ + ASSERT(mpData->mpKey); + + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetModulus().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetExponent().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetPrime1().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetPrime2().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetDecryptionExponent().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterDP().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterDQ().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterU().IsPositive()); + + int len = sizeof(int16) + + mpData->mpKey->GetTrapdoorFunction().GetModulus().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetExponent().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetPrime1().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetPrime2().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetDecryptionExponent().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetParameterDP().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetParameterDQ().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetParameterU().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32); + + return len; +} + +void cRSAPrivateKey::Write(void* pDataStream) const +{ + ASSERT(mpData->mpKey); + + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetModulus().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetExponent().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetPrime1().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetPrime2().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetDecryptionExponent().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterDP().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterDQ().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetParameterU().IsPositive()); + + byte* pOut = (byte*)pDataStream; + int16 i16; + int32 i32; + + i16 = tw_htons(mpData->mKeyLength); + memcpy(pOut, &i16, sizeof(i16)); + pOut += sizeof(int16); + + Integer n, e, d, p, q, dp, dq, u; + + n = mpData->mpKey->GetTrapdoorFunction().GetModulus(); + e = mpData->mpKey->GetTrapdoorFunction().GetExponent(); + p = mpData->mpKey->GetTrapdoorFunction().GetPrime1(); + q = mpData->mpKey->GetTrapdoorFunction().GetPrime2(); + d = mpData->mpKey->GetTrapdoorFunction().GetDecryptionExponent(); + dp = mpData->mpKey->GetTrapdoorFunction().GetParameterDP(); + dq = mpData->mpKey->GetTrapdoorFunction().GetParameterDQ(); + u = mpData->mpKey->GetTrapdoorFunction().GetParameterU(); + + int32 len; + +#define WRITE_INTEGER(I) \ + len = I.MinEncodedSize(Integer::UNSIGNED); \ + i32 = tw_htonl(len); \ + memcpy(pOut, &i32, sizeof(i32)); \ + pOut += sizeof(int32); \ + I.Encode(pOut, len, Integer::UNSIGNED); \ + pOut += len; + + WRITE_INTEGER(n); + WRITE_INTEGER(e); + WRITE_INTEGER(d); + WRITE_INTEGER(p); + WRITE_INTEGER(q); + WRITE_INTEGER(dp); + WRITE_INTEGER(dq); + WRITE_INTEGER(u); +} + +// class cRSAPublicKey + +class cRSAPublicKey_i +{ +public: + int16 mKeyLength; + RSAPublicKey* mpKey; +}; + +cRSAPublicKey::cRSAPublicKey() +{ + mpData = new cRSAPublicKey_i; + mpData->mpKey = 0; + mpData->mKeyLength = 0; +} + +cRSAPublicKey::cRSAPublicKey(void* pDataStream) +{ + mpData = new cRSAPublicKey_i; + + Integer n, e; + int32 len; + int16 i16; + int32 i32; + + byte* pIn = (byte*)pDataStream; + + memcpy(&i16, pIn, sizeof(i16)); + mpData->mKeyLength = tw_ntohs(i16); + pIn += sizeof(int16); + + READ_INTEGER(n); + READ_INTEGER(e); + + //std::cout << "cRSAPublicKey n = " << n << std::endl; + //std::cout << "cRSAPublicKey e = " << e << std::endl; + + mpData->mpKey = new RSAPublicKey(n, e); +} + +cRSAPublicKey::cRSAPublicKey(const cRSAPrivateKey& privateKey) +{ + mpData = new cRSAPublicKey_i; + + ASSERT(privateKey.mpData); + ASSERT(privateKey.mpData->mpKey); + + mpData->mKeyLength = privateKey.mpData->mKeyLength; + mpData->mpKey = new RSAPublicKey(*privateKey.mpData->mpKey); +} + +cRSAPublicKey::~cRSAPublicKey() +{ + if (mpData) + { + delete mpData->mpKey; + delete mpData; + } +} + +int cRSAPublicKey::GetWriteLen() const +{ + ASSERT(mpData->mpKey); + + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetModulus().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetExponent().IsPositive()); + + int len = sizeof(int16) + + mpData->mpKey->GetTrapdoorFunction().GetModulus().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetTrapdoorFunction().GetExponent().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32); + + return len; +} + +void cRSAPublicKey::Write(void* pDataStream) const +{ + ASSERT(mpData->mpKey); + + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetModulus().IsPositive()); + ASSERT(mpData->mpKey->GetTrapdoorFunction().GetExponent().IsPositive()); + + int16 i16; + int32 i32; + byte* pOut = (byte*)pDataStream; + + i16 = tw_htons(mpData->mKeyLength); + memcpy(pOut, &i16, sizeof(i16)); + pOut += sizeof(int16); + + Integer n, e; + + n = mpData->mpKey->GetTrapdoorFunction().GetModulus(); + e = mpData->mpKey->GetTrapdoorFunction().GetExponent(); + + int32 len; + + WRITE_INTEGER(n); + WRITE_INTEGER(e); +} + +#ifdef _DEBUG +void cRSAPublicKey::TraceContents() +{ + cDebug d("cRSAPublicKey::TraceContents"); + + { + std::ostringstream os; + os << mpData->mpKey->GetTrapdoorFunction().GetModulus(); + d.TraceDebug("Modulus = %s\n", os.str().c_str()); + } + { + std::ostringstream os; + os << mpData->mpKey->GetTrapdoorFunction().GetExponent(); + d.TraceDebug("Exponent = %s\n", os.str().c_str()); + } +} +#endif + +// class cRSA + +class cRSA_i +{ +public: + int mKeyBits; + + enum Action { ENCRYPT, DECRYPT, SIGN, VERIFY }; + + Action mAction; + + const cRSAPrivateKey* mpPrivateKey; + const cRSAPublicKey* mpPublicKey; + + X917RNG* mpRNG; +}; + +cRSA::cRSA(KeySize keysize) +{ + Init(keysize); +} + +cRSA::cRSA(const cRSAPublicKey& publicKey) +{ + ASSERT(publicKey.mpData); + Init((KeySize)publicKey.mpData->mKeyLength); +} + +cRSA::cRSA(const cRSAPrivateKey& privateKey) +{ + ASSERT(privateKey.mpData); + Init((KeySize)privateKey.mpData->mKeyLength); +} + +void cRSA::Init(KeySize keysize) +{ + mpData = new cRSA_i; + mpData->mpPrivateKey = 0; + mpData->mpPublicKey = 0; + + mpData->mKeyBits = (keysize == KEY256) ? 256 : + (keysize == KEY512) ? 512 : + (keysize == KEY1024) ? 1024 : + (keysize == KEY2048) ? 2048 : + 256; + + // Create a random seed and a key + byte seed[MD5::DATASIZE]; + byte deskey[TripleDES_Encryption::KEYLENGTH]; + RandomizeBytes((int8*)seed, MD5::DATASIZE); + RandomizeBytes((int8*)deskey, TripleDES_Encryption::KEYLENGTH); + + mpData->mpRNG = new X917RNG(new TripleDES_Encryption(deskey), seed); +} + +cRSA::~cRSA() +{ + if (mpData) + { + delete mpData->mpRNG; + delete mpData; + mpData = 0; + } +} + +void cRSA::SetEncrypting(const cRSAPublicKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("RSA Key length mismatch."))); + + + mpData->mAction = cRSA_i::ENCRYPT; + mpData->mpPublicKey = pKey; + mpData->mpPrivateKey = 0; +} + +void cRSA::SetDecrypting(const cRSAPrivateKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("RSA Key length mismatch."))); + + mpData->mAction = cRSA_i::DECRYPT; + mpData->mpPrivateKey = pKey; + mpData->mpPublicKey = 0; +} + +void cRSA::SetSigning(const cRSAPrivateKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("RSA Key length mismatch."))); + + mpData->mAction = cRSA_i::SIGN; + mpData->mpPrivateKey = pKey; + mpData->mpPublicKey = 0; +} + +void cRSA::SetVerifying(const cRSAPublicKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("RSA Key length mismatch."))); + + mpData->mAction = cRSA_i::VERIFY; + mpData->mpPublicKey = pKey; + mpData->mpPrivateKey = 0; +} + +// Lets encrypt in 128 bit chunks, even though the crypto +// lib implementation can do arbitrary length plaintext +// encryptions. We will most likely only use this to +// encrypt a 128 bit random number anyway. +int cRSA::GetBlockSizePlain() +{ + //Integer i = mpData->mKeyBits - 1; + + return (mpData->mKeyBits >> 3) - 11; +} + +int cRSA::GetBlockSizeCipher() +{ + return mpData->mKeyBits >> 3; +} + +void cRSA::ProcessBlock(const void* indata, void* outdata) +{ + ASSERT(mpData); + ASSERT(mpData->mpPrivateKey != 0 || mpData->mpPublicKey != 0); + + if (mpData->mpPrivateKey == 0 && mpData->mpPublicKey == 0) + ThrowAndAssert(eInternal(_T("RSA Key length mismatch."))); + + unsigned int l; + + switch (mpData->mAction) + { + case cRSA_i::ENCRYPT: + { + ASSERT(mpData->mpPublicKey); + ASSERT(mpData->mpPublicKey->mpData->mpKey->MaxPlainTextLength() == GetBlockSizePlain()); + ASSERT(mpData->mpPublicKey->mpData->mpKey->CipherTextLength() == GetBlockSizeCipher()); + mpData->mpPublicKey->mpData->mpKey->Encrypt(*mpData->mpRNG, (const byte *)indata, GetBlockSizePlain(), (byte *)outdata); + break; + } + case cRSA_i::DECRYPT: + { + ASSERT(mpData->mpPrivateKey); + ASSERT(mpData->mpPrivateKey->mpData->mpKey->CipherTextLength() == GetBlockSizeCipher()); + l = mpData->mpPrivateKey->mpData->mpKey->Decrypt((const byte *)indata, (byte *)outdata); + if (l != GetBlockSizePlain()) + throw eArchiveCrypto(); + break; + } + case cRSA_i::SIGN: + { + ASSERT(mpData->mpPrivateKey); + ASSERT(mpData->mpPrivateKey->mpData->mpKey->MaxMessageLength() == GetBlockSizePlain()); + ASSERT(mpData->mpPrivateKey->mpData->mpKey->SignatureLength() == GetBlockSizeCipher()); + mpData->mpPrivateKey->mpData->mpKey->Sign(*mpData->mpRNG, (const byte *)indata, GetBlockSizePlain(), (byte *)outdata); + break; + } + case cRSA_i::VERIFY: + { + ASSERT(mpData->mpPublicKey); + ASSERT(mpData->mpPublicKey->mpData->mpKey->SignatureLength() == GetBlockSizeCipher()); + l = mpData->mpPublicKey->mpData->mpKey->Recover((const byte *)indata, (byte *)outdata); + if (l != GetBlockSizePlain()) + throw eArchiveCrypto(); + break; + } + default: + { + ASSERT(false); + break; + } + } +} + +void cRSA::GenerateKeys(cRSAPrivateKey*& retPrivate, cRSAPublicKey*& retPublic) +{ + RSAPrivateKey* pNewPrivateKey = new RSAPrivateKey(*mpData->mpRNG, mpData->mKeyBits); + RSAPublicKey* pNewPublicKey = new RSAPublicKey(*pNewPrivateKey); + + retPrivate = new cRSAPrivateKey(); + retPrivate->mpData->mpKey = pNewPrivateKey; + retPrivate->mpData->mKeyLength = mpData->mKeyBits; + + retPublic = new cRSAPublicKey(); + retPublic->mpData->mpKey = pNewPublicKey; + retPublic->mpData->mKeyLength = mpData->mKeyBits; + +#ifdef _DEBUG + int l; + l = retPublic->mpData->mpKey->MaxPlainTextLength(); + ASSERT(l == GetBlockSizePlain()); + l = retPublic->mpData->mpKey->CipherTextLength(); + ASSERT(l == GetBlockSizeCipher()); + l = retPrivate->mpData->mpKey->CipherTextLength(); + ASSERT(l == GetBlockSizeCipher()); +#endif +} + +#endif // _RSA_ENCRYPTION + +/////////////////////////////////////////////////////////////////////////////// +// class cElGamalSig + +// class cElGamalSigPrivateKey + +class cElGamalSigPrivateKey_i +{ +public: + int16 mKeyLength; + ElGamalSigPrivateKey* mpKey; +}; + +cElGamalSigPrivateKey::cElGamalSigPrivateKey() +{ + mpData = new cElGamalSigPrivateKey_i; + mpData->mpKey = 0; + mpData->mKeyLength = 0; +} + +cElGamalSigPrivateKey::cElGamalSigPrivateKey(void* pDataStream) +{ + mpData = new cElGamalSigPrivateKey_i; + + int32 len; + int32 i32; + int16 i16; + uint32 magicNum; + + byte* pIn = (byte*)pDataStream; + + memcpy(&i16, pIn, sizeof(i16)); + mpData->mKeyLength = tw_ntohs(i16); + pIn += sizeof(int16); + + memcpy(&i32, pIn, sizeof(i32)); + magicNum = tw_ntohl(i32); + pIn += sizeof(int32); + + if (magicNum != EL_GAMAL_SIG_PRIVATE_MAGIC_NUM) + ThrowAndAssert( eArchiveOpen() ); + + Integer p, q, g, y, x; + + READ_INTEGER(p); + READ_INTEGER(q); + READ_INTEGER(g); + READ_INTEGER(y); + READ_INTEGER(x); + + mpData->mpKey = new ElGamalSigPrivateKey(p, q, g, y, x); +} + +cElGamalSigPrivateKey::~cElGamalSigPrivateKey() +{ + if (mpData) + { + delete mpData->mpKey; + delete mpData; + } +} + +int cElGamalSigPrivateKey::GetWriteLen() const +{ + ASSERT(mpData->mpKey != 0); + + ASSERT(mpData->mpKey->GetPrime().IsPositive()); + ASSERT(mpData->mpKey->GetParameterQ().IsPositive()); + ASSERT(mpData->mpKey->GetParameterG().IsPositive()); + ASSERT(mpData->mpKey->GetParameterY().IsPositive()); + ASSERT(mpData->mpKey->GetParameterX().IsPositive()); + + int len = sizeof(int16) + sizeof(int32) + + mpData->mpKey->GetPrime().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterQ().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterG().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterY().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterX().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32); + + return len; +} + +void cElGamalSigPrivateKey::Write(void* pDataStream) const +{ + ASSERT(mpData->mpKey != 0); + + ASSERT(mpData->mpKey->GetPrime().IsPositive()); + ASSERT(mpData->mpKey->GetParameterQ().IsPositive()); + ASSERT(mpData->mpKey->GetParameterG().IsPositive()); + ASSERT(mpData->mpKey->GetParameterY().IsPositive()); + ASSERT(mpData->mpKey->GetParameterX().IsPositive()); + + byte* pOut = (byte*)pDataStream; + int16 i16; + int32 i32; + + i16 = tw_htons(mpData->mKeyLength); + memcpy(pOut, &i16, sizeof(i16)); + pOut += sizeof(int16); + + i32 = tw_htonl(EL_GAMAL_SIG_PRIVATE_MAGIC_NUM); + memcpy(pOut, &i32, sizeof(i32)); + pOut += sizeof(int32); + + Integer p, q, g, y, x; + + p = mpData->mpKey->GetPrime(); + q = mpData->mpKey->GetParameterQ(); + g = mpData->mpKey->GetParameterG(); + y = mpData->mpKey->GetParameterY(); + x = mpData->mpKey->GetParameterX(); + + int32 len; + + WRITE_INTEGER(p); + WRITE_INTEGER(q); + WRITE_INTEGER(g); + WRITE_INTEGER(y); + WRITE_INTEGER(x); +} + +// class cElGamalSigPublicKey + +class cElGamalSigPublicKey_i +{ +public: + int16 mKeyLength; + ElGamalSigPublicKey* mpKey; +}; + +cElGamalSigPublicKey::cElGamalSigPublicKey() +{ + mpData = new cElGamalSigPublicKey_i; + mpData->mpKey = 0; + mpData->mKeyLength = 0; +} + +cElGamalSigPublicKey::cElGamalSigPublicKey(void* pDataStream) +{ + mpData = new cElGamalSigPublicKey_i; + + Integer p, q, g, y; + int32 len; + int16 i16; + int32 i32; + uint32 magicNum; + + byte* pIn = (byte*)pDataStream; + + memcpy(&i16, pIn, sizeof(i16)); + mpData->mKeyLength = tw_ntohs(i16); + pIn += sizeof(int16); + + memcpy(&i32, pIn, sizeof(i32)); + magicNum = tw_ntohl(i32); + pIn += sizeof(int32); + + if (magicNum != EL_GAMAL_SIG_PUBLIC_MAGIC_NUM) + ThrowAndAssert( eArchiveOpen() ); + + READ_INTEGER(p); + READ_INTEGER(q); + READ_INTEGER(g); + READ_INTEGER(y); + + //std::cout << "cElGamalSigPublicKey n = " << n << std::endl; + //std::cout << "cElGamalSigPublicKey e = " << e << std::endl; + + mpData->mpKey = new ElGamalSigPublicKey(p, q, g, y); +} + +cElGamalSigPublicKey::cElGamalSigPublicKey(const cElGamalSigPrivateKey& privateKey) +{ + mpData = new cElGamalSigPublicKey_i; + + ASSERT(privateKey.mpData != 0); + ASSERT(privateKey.mpData->mpKey != 0); + + mpData->mKeyLength = privateKey.mpData->mKeyLength; + mpData->mpKey = new ElGamalSigPublicKey(*privateKey.mpData->mpKey); +} + +cElGamalSigPublicKey::~cElGamalSigPublicKey() +{ + if (mpData) + { + delete mpData->mpKey; + delete mpData; + } +} + +int cElGamalSigPublicKey::GetWriteLen() const +{ + ASSERT(mpData->mpKey != 0); + + ASSERT(mpData->mpKey->GetPrime().IsPositive()); + ASSERT(mpData->mpKey->GetParameterQ().IsPositive()); + ASSERT(mpData->mpKey->GetParameterG().IsPositive()); + ASSERT(mpData->mpKey->GetParameterY().IsPositive()); + + int len = sizeof(int16) + sizeof(int32) + + mpData->mpKey->GetPrime().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterQ().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterG().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32) + + mpData->mpKey->GetParameterY().MinEncodedSize(Integer::UNSIGNED) + sizeof(int32); + + return len; + +} + +void cElGamalSigPublicKey::Write(void* pDataStream) const +{ + ASSERT(mpData->mpKey != 0); + + ASSERT(mpData->mpKey->GetPrime().IsPositive()); + ASSERT(mpData->mpKey->GetParameterQ().IsPositive()); + ASSERT(mpData->mpKey->GetParameterG().IsPositive()); + ASSERT(mpData->mpKey->GetParameterY().IsPositive()); + + byte* pOut = (byte*)pDataStream; + int16 i16; + int32 i32; + + i16 = tw_htons(mpData->mKeyLength); + memcpy(pOut, &i16, sizeof(i16)); + pOut += sizeof(int16); + + i32 = tw_htonl(EL_GAMAL_SIG_PUBLIC_MAGIC_NUM); + memcpy(pOut, &i32, sizeof(i32)); + pOut += sizeof(int32); + + Integer p, q, g, y; + + p = mpData->mpKey->GetPrime(); + q = mpData->mpKey->GetParameterQ(); + g = mpData->mpKey->GetParameterG(); + y = mpData->mpKey->GetParameterY(); + + int32 len; + + WRITE_INTEGER(p); + WRITE_INTEGER(q); + WRITE_INTEGER(g); + WRITE_INTEGER(y); +} + +bool cElGamalSigPublicKey::IsEqual(const cElGamalSigPublicKey& rhs) const +{ + return this->mpData->mpKey->GetPrime() == rhs.mpData->mpKey->GetPrime() && + this->mpData->mpKey->GetParameterQ() == rhs.mpData->mpKey->GetParameterQ() && + this->mpData->mpKey->GetParameterG() == rhs.mpData->mpKey->GetParameterG() && + this->mpData->mpKey->GetParameterY() == rhs.mpData->mpKey->GetParameterY() + ; +} + +#ifdef _DEBUG +void cElGamalSigPublicKey::TraceContents() +{ + cDebug d("cElGamalSigPublicKey::TraceContents"); + + { + std::ostringstream os; + os << mpData->mpKey->GetPrime(); + d.TraceDebug("Prime = %s\n", os.str().c_str()); + } + { + std::ostringstream os; + os << mpData->mpKey->GetParameterQ(); + d.TraceDebug("Q = %s\n", os.str().c_str()); + } + { + std::ostringstream os; + os << mpData->mpKey->GetParameterG(); + d.TraceDebug("G = %s\n", os.str().c_str()); + } + { + std::ostringstream os; + os << mpData->mpKey->GetParameterY(); + d.TraceDebug("Y = %s\n", os.str().c_str()); + } +} +#endif + +// class cElGamalSig + +class cElGamalSig_i +{ +public: + int mKeyBits; + + enum Action { /*ENCRYPT, DECRYPT,*/ SIGN, VERIFY }; + + Action mAction; + + const cElGamalSigPrivateKey* mpPrivateKey; + const cElGamalSigPublicKey* mpPublicKey; + + SHA mSHA; + X917RNG* mpRNG; +}; + +cElGamalSig::cElGamalSig(KeySize keysize) +{ + Init(keysize); +} + +cElGamalSig::cElGamalSig(const cElGamalSigPublicKey& publicKey) +{ + ASSERT(publicKey.mpData != 0); + Init((KeySize)publicKey.mpData->mKeyLength); +} + +cElGamalSig::cElGamalSig(const cElGamalSigPrivateKey& privateKey) +{ + ASSERT(privateKey.mpData != 0); + Init((KeySize)privateKey.mpData->mKeyLength); +} + +void cElGamalSig::Init(KeySize keysize) +{ + mpData = new cElGamalSig_i; + mpData->mpPrivateKey = 0; + mpData->mpPublicKey = 0; + + mpData->mKeyBits = (keysize == KEY256) ? 256 : + (keysize == KEY512) ? 512 : + (keysize == KEY1024) ? 1024 : + (keysize == KEY2048) ? 2048 : + 256; + + // Create a random seed and a key + byte seed[SHA::DATASIZE]; + byte deskey[TripleDES_Encryption::KEYLENGTH]; + RandomizeBytes((int8*)seed, SHA::DATASIZE); + RandomizeBytes((int8*)deskey, TripleDES_Encryption::KEYLENGTH); + + mpData->mpRNG = new X917RNG(new TripleDES_Encryption(deskey), seed); +} + +cElGamalSig::~cElGamalSig() +{ + if (mpData) + { + delete mpData->mpRNG; + delete mpData; + mpData = 0; + } +} + +void cElGamalSig::SetSigning(const cElGamalSigPrivateKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("Signature Key length mismatch."))); + + mpData->mAction = cElGamalSig_i::SIGN; + mpData->mpPrivateKey = pKey; + mpData->mpPublicKey = 0; +} + +void cElGamalSig::SetVerifying(const cElGamalSigPublicKey* pKey) +{ + ASSERT(pKey->mpData->mKeyLength == mpData->mKeyBits); + if (pKey->mpData->mKeyLength != mpData->mKeyBits) + ThrowAndAssert(eInternal(_T("Signature Key length mismatch."))); + + mpData->mAction = cElGamalSig_i::VERIFY; + mpData->mpPublicKey = pKey; + mpData->mpPrivateKey = 0; +} + +int cElGamalSig::GetBlockSizePlain() +{ + return PLAIN_BLOCK_SIZE; +} + +int cElGamalSig::GetBlockSizeCipher() +{ + return PLAIN_BLOCK_SIZE + (NumberTheory::DiscreteLogWorkFactor(mpData->mKeyBits) >> 1) + 4; + // got this from nbtheory.cpp in crypto++ lib + // El Gamal's sig size = 2 * 2 * (DiscreteLogWorkFactor() >> 3) +} + +void cElGamalSig::ProcessBlock(const void* indata, void* outdata) +{ + ASSERT(mpData != 0); + ASSERT(mpData->mpPrivateKey != 0 || mpData->mpPublicKey != 0); + + int8 shaSig[SHA::DIGESTSIZE]; + + if (mpData->mpPrivateKey == 0 && mpData->mpPublicKey == 0) + ThrowAndAssert(eInternal(_T("Signature Key length mismatch."))); + + switch (mpData->mAction) + { + case cElGamalSig_i::SIGN: + { + ASSERT(mpData->mpPrivateKey != 0); + ASSERT((int)mpData->mpPrivateKey->mpData->mpKey->SignatureLength() + PLAIN_BLOCK_SIZE <= GetBlockSizeCipher()); + + memmove(outdata, indata, PLAIN_BLOCK_SIZE); + + mpData->mSHA.CalculateDigest((byte*)shaSig, (byte*)outdata, PLAIN_BLOCK_SIZE); + + RandomizeBytes((int8 *)outdata + PLAIN_BLOCK_SIZE, GetBlockSizeCipher() - PLAIN_BLOCK_SIZE); + mpData->mpPrivateKey->mpData->mpKey->Sign(*mpData->mpRNG, (const byte *)shaSig, SHA::DIGESTSIZE, (byte *)outdata + PLAIN_BLOCK_SIZE); + + /* + Integer m((const byte*)indata, PLAIN_BLOCK_SIZE); + + std::cout << "Signing:\n"; + std::cout << "M = " << m << std::endl; + + const byte* signature = (const byte *)outdata + PLAIN_BLOCK_SIZE; + int qLen = mpData->mpPrivateKey->mpData->mpKey->q.ByteCount(); + Integer rs(signature, qLen); + Integer ss(signature+qLen, qLen); + std::cout << "Stored R = " << rs << std::endl; + std::cout << "Stored S = " << ss << std::endl; + */ + + break; + } + case cElGamalSig_i::VERIFY: + { + ASSERT(mpData->mpPublicKey != 0); + ASSERT((int)mpData->mpPublicKey->mpData->mpKey->SignatureLength() + PLAIN_BLOCK_SIZE <= GetBlockSizeCipher()); + + mpData->mSHA.CalculateDigest((byte*)shaSig, (byte*)indata, PLAIN_BLOCK_SIZE); + + /* + const byte* signature = (const byte *)indata + PLAIN_BLOCK_SIZE; + int qLen = mpData->mpPublicKey->mpData->mpKey->q.ByteCount(); + Integer m((const byte*)indata, PLAIN_BLOCK_SIZE); + Integer r(signature, qLen); + Integer s(signature+qLen, qLen); + std::cout << "Verifying:\n"; + std::cout << "M = " << m << std::endl; + std::cout << "R = " << r << std::endl; + std::cout << "S = " << s << std::endl; + */ + + if (mpData->mpPublicKey->mpData->mpKey->Verify((const byte *)shaSig, SHA::DIGESTSIZE, (const byte *)indata + PLAIN_BLOCK_SIZE) == false) + throw eArchiveCrypto(); + memmove(outdata, indata, PLAIN_BLOCK_SIZE); + break; + } + default: + { + ASSERT(false); + break; + } + } +} + +void cElGamalSig::GenerateKeys(cElGamalSigPrivateKey*& retPrivate, cElGamalSigPublicKey*& retPublic) +{ + ElGamalSigPrivateKey* pNewPrivateKey = new ElGamalSigPrivateKey(*mpData->mpRNG, mpData->mKeyBits); + ElGamalSigPublicKey* pNewPublicKey = new ElGamalSigPublicKey(*pNewPrivateKey); + + retPrivate = new cElGamalSigPrivateKey(); + retPrivate->mpData->mpKey = pNewPrivateKey; + retPrivate->mpData->mKeyLength = (int16)mpData->mKeyBits; + + retPublic = new cElGamalSigPublicKey(); + retPublic->mpData->mpKey = pNewPublicKey; + retPublic->mpData->mKeyLength = (int16)mpData->mKeyBits; + +#ifdef _DEBUG + int l; + l = retPublic->mpData->mpKey->SignatureLength(); + ASSERT(l + PLAIN_BLOCK_SIZE <= GetBlockSizeCipher()); + l = retPrivate->mpData->mpKey->SignatureLength(); + ASSERT(l + PLAIN_BLOCK_SIZE <= GetBlockSizeCipher()); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// class cHashedKey128 -- A 128 bit key based on the hash value of some data + +cHashedKey128::cHashedKey128(const TSTRING& data) +{ + SHA sha; + + ASSERT(SHA::DIGESTSIZE >= KEYLEN); + sha.CalculateDigest((byte*)mKey, (byte*)data.data(), data.length() * sizeof(TCHAR)); +} + +cHashedKey128::cHashedKey128(void* pData, int dataLen) +{ + SHA sha; + + ASSERT(SHA::DIGESTSIZE >= KEYLEN); + ASSERT(SHA::DIGESTSIZE <= BUFSIZE); + sha.CalculateDigest((byte*)mKey, (byte*)pData, dataLen); +} + +cHashedKey128::~cHashedKey128() +{ + RandomizeBytes(mKey, KEYLEN); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cHashedKey192 -- A 192 bit key based on the hash value of some data + +cHashedKey192::cHashedKey192(const TSTRING& data) +{ + SHA sha; + + ASSERT(SHA::DIGESTSIZE == 20); + ASSERT(40 >= KEYLEN); + + byte localKey[40]; + sha.CalculateDigest(localKey, (byte*)data.data(), data.length() * sizeof(TCHAR)); + sha.CalculateDigest(localKey + 20, localKey, 20); + memcpy(mKey, localKey, KEYLEN); +} + +cHashedKey192::cHashedKey192(void* pData, int dataLen) +{ + SHA sha; + + ASSERT(SHA::DIGESTSIZE == 20); + ASSERT(40 >= KEYLEN); + + byte localKey[40]; + sha.CalculateDigest(localKey, (byte*)pData, dataLen); + sha.CalculateDigest(localKey + 20, localKey, 20); + memcpy(mKey, localKey, KEYLEN); +} + +cHashedKey192::~cHashedKey192() +{ + RandomizeBytes(mKey, KEYLEN); +} + +/////////////////////////////////////////////////////////////////////////////// +// void RandomizeBytes(byte* destbuf, int len) -- Fill a buffer with random bytes + +static bool gRandomizeBytesSeeded = false; + +void RandomizeBytes(int8* destbuf, int len) +{ + if (!gRandomizeBytesSeeded) + { + // generate a rancom number from processor timing. + // this should be fairly unpredictable. + time_t mask, start = time(NULL); + for (mask = 0xb147688c; time(NULL) - start < 1; mask += 0x8984cc88) + ; + + #ifdef _DEBUG + time_t t = time(NULL); + t ^= mask; + + //time_t t = 920492046 - 3600; // try to the same random values each time + //std::cerr << (*(time_t*)mask()) << ":" << t << std::endl; + + srand( t ); + #else + srand( time(NULL) ^ mask ); + #endif + gRandomizeBytesSeeded = true; + } + + int i; + for (i = 0; i < len; ++i) + destbuf[i] = (byte)( (rand() * 256 / RAND_MAX) ^ 0xdc ); // 0xdc came from random.org +} + diff --git a/src/twcrypto/crypto.h b/src/twcrypto/crypto.h new file mode 100644 index 0000000..ffbeb5b --- /dev/null +++ b/src/twcrypto/crypto.h @@ -0,0 +1,407 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// crypto.h -- Tripwire crypto header +// + +#ifndef __CRYPTO_H +#define __CRYPTO_H + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class iCipher + +class iCipher +{ +public: + virtual ~iCipher() {} + + enum EncryptionDir { ENCRYPT, DECRYPT }; + + virtual int GetBlockSizePlain() = 0; + virtual int GetBlockSizeCipher() = 0; + // return the size of data blocks this crypter works on. + virtual void ProcessBlock(const void* indata, void* outdata) = 0; // throw eArchive + // process a block of data. indata and outdata may be the same memory +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cNullCipher -- no encryption cipher + +class cNullCipher : public iCipher +{ +public: + cNullCipher() {} + virtual ~cNullCipher() {} + + virtual int GetBlockSizePlain(); + virtual int GetBlockSizeCipher(); + // return the size of data blocks for plaintext and cipertext + virtual void ProcessBlock(const void* indata, void* outdata); + // process a block of data. indata and outdata may be the same memory +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cIDEACipher + +#ifdef _IDEA_ENCRYPTION +class cIDEA_i; +class cHashedKey128; + +class cIDEA : public iCipher +{ +public: + cIDEA(); + virtual ~cIDEA(); + + void SetKey(iCipher::EncryptionDir dir, const cHashedKey128& key); + + virtual int GetBlockSizePlain(); + virtual int GetBlockSizeCipher(); + // return the size of data blocks for plaintext and cipertext + virtual void ProcessBlock(const void* indata, void* outdata); + // process a block of data. indata and outdata may be the same memory + +protected: + cIDEA_i* mpData; +}; +#endif // _IDEA_ENCRYPTION + +/////////////////////////////////////////////////////////////////////////////// +// class cTripleDES + +class cTripleDES_i; +class cHashedKey192; + +class cTripleDES : public iCipher +{ +public: + cTripleDES(); + virtual ~cTripleDES(); + + void SetKey(iCipher::EncryptionDir dir, const cHashedKey192& key); + + virtual int GetBlockSizePlain(); + virtual int GetBlockSizeCipher(); + // return the size of data blocks for plaintext and cipertext + virtual void ProcessBlock(const void* indata, void* outdata); + // process a block of data. indata and outdata may be the same memory + +protected: + cTripleDES_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cRSA + +#ifdef _RSA_ENCRYPTION + +class cRSA_i; +class cRSAPublicKey; +class cRSAPrivateKey; + +class cRSA : public iCipher +{ +public: + enum KeySize + { + KEY256 = 256, + KEY512 = 512, + KEY1024 = 1024, + KEY2048 = 2048 + }; + + cRSA(KeySize keysize); + cRSA(const cRSAPublicKey& publicKey); // read keysize from key + cRSA(const cRSAPrivateKey& privateKey); // ditto + virtual ~cRSA(); + + void SetEncrypting(const cRSAPublicKey* pKey); + void SetDecrypting(const cRSAPrivateKey* pKey); + void SetSigning(const cRSAPrivateKey* pKey); + void SetVerifying(const cRSAPublicKey* pKey); + + virtual int GetBlockSizePlain(); + virtual int GetBlockSizeCipher(); + // return the size of data blocks for plaintext and cipertext + virtual void ProcessBlock(const void* indata, void* outdata); + // process a block of data. indata and outdata may be the same memory + + void GenerateKeys(cRSAPrivateKey*& retPrivate, cRSAPublicKey*& retPublic); + // generate public and private keys. Caller is responsible for deleting these keys when done + +protected: + cRSA_i* mpData; + +private: + void Init(KeySize keysize); +}; + +class cRSAPrivateKey_i; +class cRSAPublicKey_i; + +// cRSAPrivateKey + +class cRSAPrivateKey +{ + friend class cRSA; + friend class cRSAPublicKey; +public: + cRSAPrivateKey(void* pDataStream); + ~cRSAPrivateKey(); + + int GetWriteLen() const; + void Write(void* pDataStream) const; + +protected: + cRSAPrivateKey_i* mpData; + +private: + cRSAPrivateKey(); // cRSA should be used to generate keys +}; + +// cRSAPublicKey + +class cRSAPublicKey +{ + friend class cRSA; +public: + cRSAPublicKey(void* pDataStream); + cRSAPublicKey(const cRSAPrivateKey& privateKey); + ~cRSAPublicKey(); + + int GetWriteLen() const; + void Write(void* pDataStream) const; + +#ifdef _DEBUG + void TraceContents(); +#endif + +protected: + cRSAPublicKey_i* mpData; + +private: + cRSAPublicKey(); // cRSA should be used to generate keys +}; + +#endif // _RSA_ENCRYPTION + + +/////////////////////////////////////////////////////////////////////////////// +// class cElGamalSig +// +// This class does not encrypt the cipher stream. For each block written +// it signs a hash of the block and appends the signature to the end of the +// block. When reading an exception will be thrown if the signature does +// not match the data. +// +// We use El Gamal because it is patent free.. +// + +class cElGamalSig_i; +class cElGamalSigPublicKey; +class cElGamalSigPrivateKey; + +class cElGamalSig : public iCipher +{ +public: + enum KeySize + { + KEY256 = 256, + KEY512 = 512, + KEY1024 = 1024, + KEY2048 = 2048 + }; + + cElGamalSig(KeySize keysize); + cElGamalSig(const cElGamalSigPublicKey& publicKey); // read keysize from key + cElGamalSig(const cElGamalSigPrivateKey& privateKey); // ditto + virtual ~cElGamalSig(); + + void SetSigning(const cElGamalSigPrivateKey* pKey); + void SetVerifying(const cElGamalSigPublicKey* pKey); + + virtual int GetBlockSizePlain(); + virtual int GetBlockSizeCipher(); + // return the size of data blocks for plaintext and cipertext + virtual void ProcessBlock(const void* indata, void* outdata); + // process a block of data. indata and outdata may be the same memory + + void GenerateKeys(cElGamalSigPrivateKey*& retPrivate, cElGamalSigPublicKey*& retPublic); + // generate public and private keys. Caller is responsible for deleting these keys when done + +protected: + cElGamalSig_i* mpData; + +private: + void Init(KeySize keysize); + + enum { PLAIN_BLOCK_SIZE = 4083 }; +}; + +class cElGamalSigPrivateKey_i; +class cElGamalSigPublicKey_i; + +// cElGamalSigPrivateKey + +class cElGamalSigPrivateKey +{ + friend class cElGamalSig; + friend class cElGamalSigPublicKey; +public: + cElGamalSigPrivateKey(void* pDataStream); + ~cElGamalSigPrivateKey(); + + int GetWriteLen() const; + void Write(void* pDataStream) const; + +protected: + cElGamalSigPrivateKey_i* mpData; + +private: + cElGamalSigPrivateKey(); // cElGamal should be used to generate keys +}; + +// cElGamalSigPublicKey + +class cElGamalSigPublicKey +{ + friend class cElGamalSig; +public: + cElGamalSigPublicKey(void* pDataStream); + cElGamalSigPublicKey(const cElGamalSigPrivateKey& privateKey); + ~cElGamalSigPublicKey(); + + int GetWriteLen() const; + void Write(void* pDataStream) const; + + bool IsEqual(const cElGamalSigPublicKey& rhs) const; + // This is used to make sure the key used to sign the config + // file is the same as the key we are currently using. + +#ifdef _DEBUG + void TraceContents(); +#endif + +protected: + cElGamalSigPublicKey_i* mpData; + +private: + cElGamalSigPublicKey(); // cElGamal should be used to generate keys +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cHashedKey128 -- A 128 bit key based on the hash value of some data + +class cHashedKey128 +{ +public: + cHashedKey128(const TSTRING& data); + cHashedKey128(void* pData, int dataLen); + ~cHashedKey128(); + + const int8* GetKey() const; + + static int GetWriteLen(); + void Write(void* pDataStream); + +protected: + enum { KEYLEN = 16, BUFSIZE = 20}; + + int8 mKey[BUFSIZE]; +}; + +inline const int8* cHashedKey128::GetKey() const +{ + return mKey; +} + +inline int cHashedKey128::GetWriteLen() +{ + return KEYLEN; +} + +inline void cHashedKey128::Write(void* pDataStream) +{ + memcpy(pDataStream, mKey, KEYLEN); +} + +/////////////////////////////////////////////////////////////////////////////// +// class cHashedKey192 -- A 192 bit key based on the hash value of some data + +class cHashedKey192 +{ +public: + cHashedKey192(const TSTRING& data); + cHashedKey192(void* pData, int dataLen); + ~cHashedKey192(); + + const int8* GetKey() const; + + static int GetWriteLen(); + void Write(void* pDataStream); + +protected: + enum { KEYLEN = 24 }; + + int8 mKey[KEYLEN]; +}; + +inline const int8* cHashedKey192::GetKey() const +{ + return mKey; +} + +inline int cHashedKey192::GetWriteLen() +{ + return KEYLEN; +} + +inline void cHashedKey192::Write(void* pDataStream) +{ + memcpy(pDataStream, mKey, KEYLEN); +} + +/////////////////////////////////////////////////////////////////////////////// +// void RandomizeBytes(byte* destbuf, int len) -- Fill a buffer with random bytes + +void RandomizeBytes(int8* destbuf, int len); + +#endif // __CRYPTO_H + diff --git a/src/twcrypto/cryptoarchive.cpp b/src/twcrypto/cryptoarchive.cpp new file mode 100644 index 0000000..4d227f8 --- /dev/null +++ b/src/twcrypto/cryptoarchive.cpp @@ -0,0 +1,751 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// cryptoarchive.cpp -- classes that abstract a raw byte archive + +#include "stdtwcrypto.h" + +#include "cryptoarchive.h" +#include "crypto.h" + +#include "cryptlib/zinflate.h" +#include "cryptlib/zdeflate.h" +// old queue +//#include "cryptlib/queue.h" +#include "bytequeue.h" + +enum mAction +{ + UNSTARTED, + UNKNOWN, + READING, + WRITING, + FINISHED +}; + +const int CRYPTO_COMPRESSION_LEVEL = 6; + + +// folowing interfaces were added to use Crypto++'s implementation +// of gzip + +// class that takes a plaintext input via Put() and +// outputs encrypted data to the passed in cArchive +class cCryptoSink : public Sink +{ +public: + cCryptoSink(cArchive* pDestArchive, iCipher* pCipher); + ~cCryptoSink(); + + virtual void Put(const byte *inString, unsigned int length); + virtual void InputFinished(); + + virtual void Put(byte inByte) { Put(&inByte, 1); } + +private: + cArchive* mpDestArchive; + iCipher* mpCipher; + + // buffer to cache bytes in + int8* mpBuffer; + int mBufferLen; + int mBufferUsed; +}; + +class cCryptoSource : public Source +{ +public: + cCryptoSource(cArchive* pSrcArchive, iCipher* pCipher, BufferedTransformation *outQueue); + ~cCryptoSource(); + + unsigned int Pump(unsigned int size); + unsigned long PumpAll(); + +private: + cArchive* mpSrcArchive; + iCipher* mpCipher; + + // buffer to cache bytes in + int8* mpBuffer; + int mBufferLen; + int mBufferUsed; +}; + +cCryptoArchive::cCryptoArchive() +{ + mpArchive = 0; + mpCipher = 0; + mpDeflator = 0; + mpInflator = 0; + mpCryptoSink = 0; + mpCryptoSource = 0; + mpInflatedBytes = 0; + mAction = UNSTARTED; +} + +cCryptoArchive::~cCryptoArchive() +{ + ASSERT(mAction == UNSTARTED || mAction == UNKNOWN || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + delete mpDeflator; + delete mpInflator; +} + +void cCryptoArchive::Start(cArchive* pArchive, iCipher* pCipher) +{ + ASSERT(mAction == UNSTARTED || mAction == UNKNOWN || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mpArchive = pArchive; + mpCipher = pCipher; + + delete mpDeflator; + mpDeflator = 0; + delete mpCryptoSink; + mpCryptoSink = 0; + delete mpInflator; + mpInflator = 0; + delete mpCryptoSource; + mpCryptoSource = 0; + delete mpInflatedBytes; + mpInflatedBytes = 0; + + mAction = UNKNOWN; +} + +int cCryptoArchive::Write(const void* pSrc, int count) +{ + if (mAction == UNKNOWN) + { + // this is the first write + mAction = WRITING; + + ASSERT(mpDeflator == 0); + ASSERT(mpCryptoSink == 0); + ASSERT(mpInflator == 0); + ASSERT(mpCryptoSource == 0); + ASSERT(mpInflatedBytes == 0); + + mpCryptoSink = new cCryptoSink(mpArchive, mpCipher); + mpDeflator = new Deflator(CRYPTO_COMPRESSION_LEVEL, mpCryptoSink); + } + else if (mAction != WRITING) + { + ASSERT(false); + throw eArchiveInvalidOp(); + } + + mpDeflator->Put((byte*)pSrc, count); + + return count; +} + +int cCryptoArchive::Read(void* pDest, int count) +{ + int len; + + if (mAction == UNKNOWN) + { + // this is the first read + mAction = READING; + + ASSERT(mpDeflator == 0); + ASSERT(mpCryptoSink == 0); + ASSERT(mpInflator == 0); + ASSERT(mpCryptoSource == 0); + ASSERT(mpInflatedBytes == 0); + + mpInflatedBytes = new cByteQueue; + mpInflator = new Inflator(mpInflatedBytes); + mpCryptoSource = new cCryptoSource(mpArchive, mpCipher, mpInflator); + } + else if (mAction != READING) + { + ASSERT(false); + throw eArchiveInvalidOp(); + } + + while ( (int)mpInflatedBytes->CurrentSize() < count ) + { + len = mpCipher->GetBlockSizePlain(); + if ( (int)mpCryptoSource->Pump(len) < len ) // RAD: Cast to int + { + mpInflator->InputFinished(); + if ( (int)mpInflatedBytes->CurrentSize() < count ) // RAD: Cast to int + { + len = mpInflatedBytes->CurrentSize(); + mpInflatedBytes->Get((byte*)pDest, len); + return len; + } + } + } + + len = mpInflatedBytes->Get((byte*)pDest, count); + ASSERT(len == count); + + return len; +} + +bool cCryptoArchive::EndOfFile() +{ + ASSERT(mAction == READING); // why would you call this if not reading? + if (mAction != READING) + return true; + + // TODO: is this right? + ASSERT(mpInflatedBytes != 0); + return mpInflatedBytes->MaxRetrieveable() == 0; +} + +// Call when done writing to the archive to flush any buffered bytes. +// An ASSERT() will occur if further reads or write are called. +// You may call when done reading to cause an ASSERT() if further +// reads are attempted. +void cCryptoArchive::Finish() +{ + if (mAction == WRITING) + { + mpDeflator->InputFinished(); + mpCryptoSink->InputFinished(); + delete mpDeflator; + mpDeflator = 0; + mpCryptoSink = 0; // mpCryptoSink is deleted by ~Deflator() + + mAction = FINISHED; + } + else if (mAction == READING) + { + delete mpCryptoSource; + mpCryptoSource = 0; + mpInflator = 0; // deleting mpCryptoSource is deleted by ~Inflator() + + mAction = FINISHED; + } + else + { + // what is up? + ASSERT(false); + } +} + +cCryptoSink::cCryptoSink(cArchive* pDestArchive, iCipher* pCipher) +{ + mpDestArchive = pDestArchive; + mpCipher = pCipher; + mpBuffer = 0; + mBufferLen = 0; + mBufferUsed = 0; +} + +cCryptoSink::~cCryptoSink() +{ + delete [] mpBuffer; +} + +void cCryptoSink::Put(const byte *inString, unsigned int length) +{ + if (mpBuffer == 0) + { + // this is the first write + mBufferLen = mpCipher->GetBlockSizePlain(); + mpBuffer = new int8[mBufferLen]; + mBufferUsed = 0; + } + + // RAD: Cast to int + ASSERT( length <= std::numeric_limits::max() ); + int nLength = static_cast( length ); + + int i = 0; + while ( i < nLength ) + { + int bytesToCopy = mBufferLen - mBufferUsed; + if (bytesToCopy > nLength - i) + bytesToCopy = nLength - i; + + memcpy(mpBuffer + mBufferUsed, (int8*)inString + i, bytesToCopy); + mBufferUsed += bytesToCopy; + + if (mBufferUsed >= mBufferLen) + { + ASSERT(mBufferUsed == mBufferLen); // should be if our math is right + + int8* pTmp = new int8[mpCipher->GetBlockSizeCipher()]; + mpCipher->ProcessBlock(mpBuffer, pTmp); + + mpDestArchive->WriteBlob(pTmp, mpCipher->GetBlockSizeCipher()); + + delete [] pTmp; + mBufferUsed = 0; + } + + i += bytesToCopy; + } + + ASSERT( i == nLength ); // should be if our math is right +} + +void cCryptoSink::InputFinished() +{ + if (mBufferUsed > 0) + { + ASSERT(mBufferLen - mBufferUsed > 0); // should be, or the buffer should have already been written + RandomizeBytes(mpBuffer + mBufferUsed, mBufferLen - mBufferUsed); + + int8* pTmp = new int8[mpCipher->GetBlockSizeCipher()]; + mpCipher->ProcessBlock(mpBuffer, pTmp); + + mpDestArchive->WriteBlob(pTmp, mpCipher->GetBlockSizeCipher()); + + delete [] pTmp; + mBufferUsed = 0; + } + + delete [] mpBuffer; + mpBuffer = 0; + mBufferLen = 0; + mBufferUsed = 0; +} + + +cCryptoSource::cCryptoSource(cArchive* pSrcArchive, iCipher* pCipher, BufferedTransformation *outQueue) +: Source(outQueue) +{ + mpSrcArchive = pSrcArchive; + mpCipher = pCipher; + + mpBuffer = 0; + mBufferLen = 0; + mBufferUsed = 0; +} + +cCryptoSource::~cCryptoSource() +{ + delete [] mpBuffer; +} + +unsigned int cCryptoSource::Pump(unsigned int size) +{ + if (mpBuffer == 0) + { + // first time this has been called + mBufferLen = mpCipher->GetBlockSizePlain(); + mpBuffer = new int8[mBufferLen]; + mBufferUsed = mBufferLen; + } + + // RAD: Cast to int (Why are these locals signed if the interface is unsigned?) + ASSERT( size <= std::numeric_limits::max() ); + int nSize = static_cast( size ); + + int i = 0; + while ( i < nSize ) + { + if (mBufferUsed >= mBufferLen) + { + ASSERT( mBufferUsed == mBufferLen ); // should be if our math is right + + int8* pTmp = new int8[mpCipher->GetBlockSizeCipher()]; + + int l = mpSrcArchive->ReadBlob( pTmp, mpCipher->GetBlockSizeCipher() ); + if ( l != mpCipher->GetBlockSizeCipher() ) + { + delete [] pTmp; + return 0; + } + + mpCipher->ProcessBlock( pTmp, mpBuffer ); + + delete [] pTmp; + mBufferUsed = 0; + } + + int bytesToCopy = mBufferLen - mBufferUsed; + if (bytesToCopy > nSize - i) + bytesToCopy = nSize - i; + + outQueue->Put( (byte*)(mpBuffer + mBufferUsed), bytesToCopy ); + + mBufferUsed += bytesToCopy; + i += bytesToCopy; + } + + ASSERT( i == nSize ); // should be if our math is right + + return i; +} + +unsigned long cCryptoSource::PumpAll() +{ + unsigned long total=0; + unsigned int l; + + if (mBufferLen == 0) + mBufferLen = mpCipher->GetBlockSizePlain(); + + while ((l=Pump(mBufferLen)) != 0) + total += l; + + return total; +} + +/////////////////////////////////////////////////////////////////////////////// +// class cNullCryptoArchive +// +// Works like crypto archive but uses no encryption. However, the compression +// functionality of cCryptoArchive is still utilized. + + +cNullCryptoArchive::cNullCryptoArchive() +{ + mpNullCipher = new cNullCipher; +} + +cNullCryptoArchive::~cNullCryptoArchive() +{ + delete mpNullCipher; +} + +void cNullCryptoArchive::Start(cArchive* pArchive) +{ + mCryptoArchive.Start(pArchive, mpNullCipher); +} + +void cNullCryptoArchive::Finish() +{ + mCryptoArchive.Finish(); +} + +bool cNullCryptoArchive::EndOfFile() +{ + return mCryptoArchive.EndOfFile(); +} + +int cNullCryptoArchive::Read(void* pDest, int count) +{ + return mCryptoArchive.ReadBlob(pDest, count); +} + +int cNullCryptoArchive::Write(const void* pSrc, int count) +{ + mCryptoArchive.WriteBlob(pSrc, count); + return count; +} + +#ifdef _RSA_ENCRYPTION +/////////////////////////////////////////////////////////////////////////////// +// class cRSAArchive + + cCryptoArchive mCryptoArchive; + + int mAction; + + cArchive* mpArchive; + cRSAPublicKey* mpPublicKey; + cRSAPrivateKey* mpPrivateKey; + +cRSAArchive::cRSAArchive() +{ + mAction = UNSTARTED; + mpArchive = 0; + mpPublicKey = 0; + mpPrivateKey = 0; + + mpIDEA = new cIDEA; +} + +cRSAArchive::~cRSAArchive() +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + delete mpIDEA; +} + +void cRSAArchive::SetWrite(cArchive* pDestArchive, const cRSAPublicKey* pPublicKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = WRITING; + mpArchive = pDestArchive; + mpPublicKey = pPublicKey; + mpPrivateKey = 0; + + // Create a random number and encode using public key + cRSA rsa(*mpPublicKey); + int8* key = new int8[rsa.GetBlockSizePlain()]; + int8* encryptedKey = new int8[rsa.GetBlockSizeCipher()]; + + RandomizeBytes(key, rsa.GetBlockSizePlain()); + rsa.SetEncrypting(mpPublicKey); + rsa.ProcessBlock(key, encryptedKey); + + mpArchive->WriteBlob(encryptedKey, rsa.GetBlockSizeCipher()); + + mpIDEA->SetKey(iCipher::ENCRYPT, cHashedKey128(key, rsa.GetBlockSizePlain())); + + // clear out key from memory + RandomizeBytes(key, rsa.GetBlockSizePlain()); + + mCryptoArchive.Start(mpArchive, mpIDEA); + + delete [] key; + delete [] encryptedKey; +} + +void cRSAArchive::SetWrite(cArchive* pDestArchive, const cRSAPrivateKey* pPrivateKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = WRITING; + mpArchive = pDestArchive; + mpPrivateKey = pPrivateKey; + mpPublicKey = 0; + + // Create a random number and encode using public key + cRSA rsa(*mpPrivateKey); + int8* key = new int8[rsa.GetBlockSizePlain()]; + int8* encryptedKey = new int8[rsa.GetBlockSizeCipher()]; + + RandomizeBytes(key, rsa.GetBlockSizePlain()); + rsa.SetSigning(mpPrivateKey); + rsa.ProcessBlock(key, encryptedKey); + + mpArchive->WriteBlob(encryptedKey, rsa.GetBlockSizeCipher()); + + mpIDEA->SetKey(iCipher::ENCRYPT, cHashedKey128(key, rsa.GetBlockSizePlain())); + mCryptoArchive.Start(mpArchive, mpIDEA); + + // clear out key from memory + RandomizeBytes(key, rsa.GetBlockSizePlain()); + + mCryptoArchive.Start(mpArchive, mpIDEA); + + delete [] key; + delete [] encryptedKey; +} + +void cRSAArchive::FlushWrite() +{ + ASSERT(mAction == WRITING); + if (mAction != WRITING) + throw eArchiveInvalidOp(); + + mCryptoArchive.Finish(); + + mAction = FINISHED; +} + +void cRSAArchive::SetRead(cArchive* pSrcArchive, const cRSAPublicKey* pPublicKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = READING; + mpArchive = pSrcArchive; + mpPublicKey = pPublicKey; + mpPrivateKey = 0; + + cRSA rsa(*mpPublicKey); + int8* key = new int8[rsa.GetBlockSizePlain()]; + int8* encryptedKey = new int8[rsa.GetBlockSizeCipher()]; + + mpArchive->ReadBlob(encryptedKey, rsa.GetBlockSizeCipher()); + rsa.SetVerifying(mpPublicKey); + rsa.ProcessBlock(encryptedKey, key); + + mpIDEA->SetKey(iCipher::DECRYPT, cHashedKey128(key, rsa.GetBlockSizePlain())); + mCryptoArchive.Start(mpArchive, mpIDEA); + + // clear out key from memory + RandomizeBytes(key, rsa.GetBlockSizePlain()); + + mCryptoArchive.Start(mpArchive, mpIDEA); + + delete [] key; + delete [] encryptedKey; +} + +void cRSAArchive::SetRead(cArchive* pSrcArchive, const cRSAPrivateKey* pPrivateKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = READING; + mpArchive = pSrcArchive; + mpPrivateKey = pPrivateKey; + mpPublicKey = 0; + + cRSA rsa(*mpPrivateKey); + int8* key = new int8[rsa.GetBlockSizePlain()]; + int8* encryptedKey = new int8[rsa.GetBlockSizeCipher()]; + + mpArchive->ReadBlob(encryptedKey, rsa.GetBlockSizeCipher()); + rsa.SetDecrypting(mpPrivateKey); + rsa.ProcessBlock(encryptedKey, key); + + mpIDEA->SetKey(iCipher::DECRYPT, cHashedKey128(key, rsa.GetBlockSizePlain())); + mCryptoArchive.Start(mpArchive, mpIDEA); + + // clear out key from memory + RandomizeBytes(key, rsa.GetBlockSizePlain()); + + mCryptoArchive.Start(mpArchive, mpIDEA); + + delete [] key; + delete [] encryptedKey; +} + +int cRSAArchive::Read(void* pDest, int count) +{ + ASSERT(mAction == READING); + if (mAction != READING) + throw eArchiveInvalidOp(); + + return mCryptoArchive.ReadBlob(pDest, count); +} + +int cRSAArchive::Write(const void* pSrc, int count) +{ + ASSERT(mAction == WRITING); + if (mAction != WRITING) + throw eArchiveInvalidOp(); + + mCryptoArchive.WriteBlob(pSrc, count); + return count; +} + +bool cRSAArchive::EndOfFile() +{ + ASSERT(mAction == READING); // why would you call this if not reading? + if (mAction != READING) + return true; + + return mCryptoArchive.EndOfFile(); +} + +#endif // _RSA_ENCRYPTION + + +/////////////////////////////////////////////////////////////////////////////// +// class cElGamalSigArchive + +cElGamalSigArchive::cElGamalSigArchive() +{ + mAction = UNSTARTED; + mpArchive = 0; + mpPublicKey = 0; + mpPrivateKey = 0; + mpElGamal = 0; +} + +cElGamalSigArchive::~cElGamalSigArchive() +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + delete mpElGamal; +} + +void cElGamalSigArchive::SetWrite(cArchive* pDestArchive, const cElGamalSigPrivateKey* pPrivateKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = WRITING; + mpArchive = pDestArchive; + mpPrivateKey = pPrivateKey; + mpPublicKey = 0; + + mpElGamal = new cElGamalSig(*mpPrivateKey); + mpElGamal->SetSigning(mpPrivateKey); + + mCryptoArchive.Start(mpArchive, mpElGamal); +} + +void cElGamalSigArchive::FlushWrite() +{ + ASSERT(mAction == WRITING); + if (mAction != WRITING) + throw eArchiveInvalidOp(); + + mCryptoArchive.Finish(); + + mAction = FINISHED; +} + +void cElGamalSigArchive::SetRead(cArchive* pSrcArchive, const cElGamalSigPublicKey* pPublicKey) +{ + ASSERT(mAction == UNSTARTED || mAction == FINISHED || mAction == READING); + // check we did not leave a buffer unwritten + + mAction = READING; + mpArchive = pSrcArchive; + mpPublicKey = pPublicKey; + mpPrivateKey = 0; + + mpElGamal = new cElGamalSig(*mpPublicKey); + + mpElGamal->SetVerifying(mpPublicKey); + + mCryptoArchive.Start(mpArchive, mpElGamal); +} + +int cElGamalSigArchive::Read(void* pDest, int count) +{ + ASSERT(mAction == READING); + if (mAction != READING) + throw eArchiveInvalidOp(); + + return mCryptoArchive.ReadBlob(pDest, count); +} + +int cElGamalSigArchive::Write(const void* pSrc, int count) +{ + ASSERT(mAction == WRITING); + if (mAction != WRITING) + throw eArchiveInvalidOp(); + + mCryptoArchive.WriteBlob(pSrc, count); + return count; +} + +bool cElGamalSigArchive::EndOfFile() +{ + ASSERT(mAction == READING); // why would you call this if not reading? + if (mAction != READING) + return true; + + return mCryptoArchive.EndOfFile(); +} + diff --git a/src/twcrypto/cryptoarchive.h b/src/twcrypto/cryptoarchive.h new file mode 100644 index 0000000..2267427 --- /dev/null +++ b/src/twcrypto/cryptoarchive.h @@ -0,0 +1,215 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// cryptoarchive.h -- Write/Read encrypted bytes to an archive + +#ifndef __CRYPTOARCHIVE_H +#define __CRYPTOARCHIVE_H + +#ifndef __ARCHIVE_H +#include "core/archive.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// class cCryptoArchive +// +// Takes an archive and a cipher. Bytes written to this archive are compressed, +// passed through the cipher, and then written to the archive provided. When +// reading, bytes are read from the provided archive, run through the cipher, +// and then decompressed. +// +// Start() must be called before the first read or write to set the archive and +// cipher. The cCryptoArchive can be reused for reading and writing, but +// Start() must be called each time. Finish() should be called when done +// writing or not all bytes will be written. +// +// An eArchive exception will be thrown if the archvie is read from after being +// written to without calling Start(); +// +// Will throw an EOF() exception if the data source runs out +// of data while reading. + +class cArchive; +class iCipher; + +// following classes are used internally, ignore them +class cCryptoSink; +class cCryptoSource; +class Deflator; +class Inflator; +class cByteQueue; + +class cCryptoArchive : public cArchive +{ +public: + cCryptoArchive(); + virtual ~cCryptoArchive(); + + // TODO: Start and Finish should be virtual so derived classes can override them + // (and in the case of RSA and ElGamal archives, throw an exception or something). + + void Start(cArchive* pArchive, iCipher* pCipher); + // Initialize this cCryptoArchive. This function may be called + // multiple times to set new dest archives and ciphers. These + // pointers will not be deleted by this class, it is the responsibility + // of the caller to do so. + void Finish(); + // Call when done writing to the archive to flush any buffered bytes. + // An ASSERT() will occur if further reads or write are called + // You may call when done reading to cause an ASSERT() if further + // reads are attempted. + + virtual bool EndOfFile(); + +protected: + cArchive* mpArchive; + iCipher* mpCipher; + + // set on first read/write or when Finish() is called + int mAction; + + // members needed for writing + Deflator* mpDeflator; + cCryptoSink* mpCryptoSink; + + // members needed for reading + Inflator* mpInflator; + cCryptoSource* mpCryptoSource; + cByteQueue* mpInflatedBytes; + + virtual int Read(void* pDest, int count); + virtual int Write(const void* pSrc, int count); // throw(eArchive); +}; + +/////////////////////////////////////////////////////////////////////////////// +// class cNullCryptoArchive +// +// Works like crypto archive but uses no encryption. However, the compression +// functionality of cCryptoArchive is still utilized. + +class cNullCipher; + +class cNullCryptoArchive : public cArchive +{ +public: + cNullCryptoArchive(); + virtual ~cNullCryptoArchive(); + + void Start(cArchive* pArchive); + void Finish(); + + virtual bool EndOfFile(); + +protected: + cCryptoArchive mCryptoArchive; + cNullCipher* mpNullCipher; + + virtual int Read(void* pDest, int count); + virtual int Write(const void* pSrc, int count); // throw(eArchive); +}; + +#ifdef _RSA_ENCRYPTION +/////////////////////////////////////////////////////////////////////////////// +// class cRSAArchive + +class cRSAPublicKey; +class cRSAPrivateKey; +class cIDEA; + +class cRSAArchive : public cArchive +{ +public: + cRSAArchive(); + ~cRSAArchive(); + + void SetWrite(cArchive* pDestArchive, const cRSAPublicKey* pPublicKey); + void SetWrite(cArchive* pDestArchive, const cRSAPrivateKey* pPrivateKey); + + void FlushWrite(); + + void SetRead(cArchive* pSrcArchive, const cRSAPublicKey* pPublicKey); + void SetRead(cArchive* pSrcArchive, const cRSAPrivateKey* pPrivateKey); + + virtual bool EndOfFile(); + +protected: + cCryptoArchive mCryptoArchive; + cIDEA* mpIDEA; + + int mAction; + + cArchive* mpArchive; + const cRSAPublicKey* mpPublicKey; + const cRSAPrivateKey* mpPrivateKey; + + virtual int Read(void* pDest, int count); + virtual int Write(const void* pSrc, int count); // throw(eArchive); +}; +#endif // _RSA_ENCRYPTION + +/////////////////////////////////////////////////////////////////////////////// +// class cElGamalSigArchive + +class cElGamalSigPublicKey; +class cElGamalSigPrivateKey; +class cElGamalSig; + +class cElGamalSigArchive : public cArchive +{ +public: + cElGamalSigArchive(); + virtual ~cElGamalSigArchive(); + + void SetWrite(cArchive* pDestArchive, const cElGamalSigPrivateKey* pPrivateKey); + + void FlushWrite(); + + void SetRead(cArchive* pSrcArchive, const cElGamalSigPublicKey* pPublicKey); + + virtual bool EndOfFile(); + +protected: + cCryptoArchive mCryptoArchive; + + int mAction; + + cArchive* mpArchive; + cElGamalSig* mpElGamal; + const cElGamalSigPublicKey* mpPublicKey; + const cElGamalSigPrivateKey* mpPrivateKey; + + virtual int Read(void* pDest, int count); + virtual int Write(const void* pSrc, int count); // throw(eArchive); +}; + +#endif // __CRYPTOARCHIVE_H + diff --git a/src/twcrypto/cryptoarchive_t.cpp b/src/twcrypto/cryptoarchive_t.cpp new file mode 100644 index 0000000..a53e153 --- /dev/null +++ b/src/twcrypto/cryptoarchive_t.cpp @@ -0,0 +1,302 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// cryptoarchive_t.cpp -- test classes that abstract a raw byte archive + +#include "stdtwcrypto.h" +#include "cryptoarchive.h" +#include "crypto.h" +#include "test/test.h" + +void TestCryptoArchive() +{ + cDebug d("TestCryptoArchive()"); + + cMemoryArchive memory(0x800000); // max size 8 meg + + const int SIZEOF_CHUNK = 7; + const int NUM_CHUNKS = 1024 * 32; // 32k + const int TEST_CHUNKSIZE = 1023 * 7; + + d.TraceDetail("Building test memory image of size %dK bytes\n", SIZEOF_CHUNK * NUM_CHUNKS / 1024); + + int8 chunk[7]; + memcpy(chunk, "1234567", 7); + + int i; + for (i = 0; i < NUM_CHUNKS; i++) + { + RandomizeBytes(chunk, 7); + memory.WriteBlob(chunk, SIZEOF_CHUNK); + } + + // Testing cCryptoArchive + +#ifdef _IDEA_ENCRYPTION + + cIDEA idea; + cHashedKey128 ideaKey(_T("puddy, puddy, puddy, poo!")); + + { + d.TraceDetail("Encrypting using symmetric key\n"); + + cFileArchive outFile; + outFile.OpenReadWrite(TEMP_DIR _T("/crypted.bin")); + + idea.SetKey(iCipher::ENCRYPT, ideaKey); + cCryptoArchive outCrypt; + outCrypt.Start(&outFile, &idea); + + for (memory.Seek(0, cBidirArchive::BEGINNING); !memory.EndOfFile(); ) + { + int8 buf[SIZEOF_CHUNK]; + memory.ReadBlob(buf, SIZEOF_CHUNK); + outCrypt.WriteBlob(buf, SIZEOF_CHUNK); + } + + outCrypt.Finish(); + } + + { + d.TraceDetail("Decrypting using symmetric key\n"); + + cFileArchive inFile; + inFile.OpenRead(TEMP_DIR _T("/crypted.bin")); + + idea.SetKey(iCipher::DECRYPT, ideaKey); + cCryptoArchive inCrypt; + inCrypt.Start(&inFile, &idea); + + int index; + for (index = 0; index < NUM_CHUNKS * SIZEOF_CHUNK; index += TEST_CHUNKSIZE) + { + int8 buf[TEST_CHUNKSIZE]; + + int s = (index + TEST_CHUNKSIZE <= NUM_CHUNKS * SIZEOF_CHUNK) + ? TEST_CHUNKSIZE + : NUM_CHUNKS * SIZEOF_CHUNK - index; + + inCrypt.ReadBlob(buf, s); + + memory.MapArchive(index, s); + TEST(memcmp(buf, memory.GetMap(), s) == 0); + } + + inCrypt.Finish(); + } + +#endif + + // Testing cElGamalSigArchive + + { + cElGamalSig cipher(cElGamalSig::KEY1024); + cElGamalSigPrivateKey* privateKey; + cElGamalSigPublicKey* publicKey; + cipher.GenerateKeys(privateKey, publicKey); + + { + // encypt using private key + d.TraceDetail("Signing using asymmetric key\n"); + + cFileArchive outFile; + outFile.OpenReadWrite(TEMP_DIR _T("/rsacrypted.bin")); + + cElGamalSigArchive outCrypt; + outCrypt.SetWrite(&outFile, privateKey); + + for (memory.Seek(0, cBidirArchive::BEGINNING); !memory.EndOfFile(); ) + { + int8 buf[SIZEOF_CHUNK]; + memory.ReadBlob(buf, SIZEOF_CHUNK); + outCrypt.WriteBlob(buf, SIZEOF_CHUNK); + } + + outCrypt.FlushWrite(); + } + + { + // decrypt using public key + d.TraceDetail("Verifying using asymmetric key\n"); + + cFileArchive inFile; + inFile.OpenRead(TEMP_DIR _T("/rsacrypted.bin")); + + cElGamalSigArchive inCrypt; + inCrypt.SetRead(&inFile, publicKey); + + int index; + for (index = 0; index < NUM_CHUNKS * SIZEOF_CHUNK; index += TEST_CHUNKSIZE) + { + int8 buf[TEST_CHUNKSIZE]; + + int s = (index + TEST_CHUNKSIZE <= NUM_CHUNKS * SIZEOF_CHUNK) + ? TEST_CHUNKSIZE + : NUM_CHUNKS * SIZEOF_CHUNK - index; + + inCrypt.ReadBlob(buf, s); + + memory.MapArchive(index, s); + TEST(memcmp(buf, memory.GetMap(), s) == 0); + } + } + + delete privateKey; + delete publicKey; + } + +#ifdef _RSA_ENCRYPTION + cRSA cipher(cRSA::KEY256); + cRSAPrivateKey* privateKey; + cRSAPublicKey* publicKey; + cipher.GenerateKeys(privateKey, publicKey); + + cIDEA idea; + cHashedKey128 ideaKey(_T("puddy, puddy, puddy, poo!")); + + const int SIZEOF_CHUNK = 7; + const int NUM_CHUNKS = 1024 * 32; // 32k + const int TEST_CHUNKSIZE = 1023 * 7; + + d.TraceDetail("Building test memory image of size %dK bytes\n", SIZEOF_CHUNK * NUM_CHUNKS / 1024); + + int8 chunk[7]; + memcpy(chunk, "1234567", 7); + + int i; + for (i = 0; i < NUM_CHUNKS; i++) + { + RandomizeBytes(chunk, 7); + memory.WriteBlob(chunk, SIZEOF_CHUNK); + } + + // Testing cRSAArchive + + { + // encypt using public key + d.TraceDetail("Encrypting using asymmetric key\n"); + + cFileArchive outFile; + outFile.OpenReadWrite(TEMP_DIR _T("/rsacrypted.bin")); + + cRSAArchive outCrypt; + outCrypt.SetWrite(&outFile, publicKey); + + for (memory.Seek(0, cBidirArchive::BEGINNING); !memory.EndOfFile(); ) + { + int8 buf[SIZEOF_CHUNK]; + memory.ReadBlob(buf, SIZEOF_CHUNK); + outCrypt.WriteBlob(buf, SIZEOF_CHUNK); + } + + outCrypt.FlushWrite(); + } + + { + // decrypt using private key + d.TraceDetail("Decrypting using asymmetric key\n"); + + cFileArchive inFile; + inFile.OpenRead(TEMP_DIR _T("/rsacrypted.bin")); + + cRSAArchive inCrypt; + inCrypt.SetRead(&inFile, privateKey); + + int index; + for (index = 0; index < NUM_CHUNKS * SIZEOF_CHUNK; index += TEST_CHUNKSIZE) + { + int8 buf[TEST_CHUNKSIZE]; + + int s = (index + TEST_CHUNKSIZE <= NUM_CHUNKS * SIZEOF_CHUNK) + ? TEST_CHUNKSIZE + : NUM_CHUNKS * SIZEOF_CHUNK - index; + + inCrypt.ReadBlob(buf, s); + + memory.MapArchive(index, s); + TEST(memcmp(buf, memory.GetMap(), s) == 0); + } + } + + { + // encypt using private key + d.TraceDetail("Signing using asymmetric key\n"); + + cFileArchive outFile; + outFile.OpenReadWrite(TEMP_DIR _T("/rsacrypted.bin")); + + cRSAArchive outCrypt; + outCrypt.SetWrite(&outFile, privateKey); + + for (memory.Seek(0, cBidirArchive::BEGINNING); !memory.EndOfFile(); ) + { + int8 buf[SIZEOF_CHUNK]; + memory.ReadBlob(buf, SIZEOF_CHUNK); + outCrypt.WriteBlob(buf, SIZEOF_CHUNK); + } + + outCrypt.FlushWrite(); + } + + { + // decrypt using public key + d.TraceDetail("Verifying using asymmetric key\n"); + + cFileArchive inFile; + inFile.OpenRead(TEMP_DIR _T("/rsacrypted.bin")); + + cRSAArchive inCrypt; + inCrypt.SetRead(&inFile, publicKey); + + int index; + for (index = 0; index < NUM_CHUNKS * SIZEOF_CHUNK; index += TEST_CHUNKSIZE) + { + int8 buf[TEST_CHUNKSIZE]; + + int s = (index + TEST_CHUNKSIZE <= NUM_CHUNKS * SIZEOF_CHUNK) + ? TEST_CHUNKSIZE + : NUM_CHUNKS * SIZEOF_CHUNK - index; + + inCrypt.ReadBlob(buf, s); + + memory.MapArchive(index, s); + TEST(memcmp(buf, memory.GetMap(), s) == 0); + } + } + + delete privateKey; + delete publicKey; + +#endif +} + + diff --git a/src/twcrypto/crytpo_t.cpp b/src/twcrypto/crytpo_t.cpp new file mode 100644 index 0000000..033b5fa --- /dev/null +++ b/src/twcrypto/crytpo_t.cpp @@ -0,0 +1,412 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// crypto-t.cpp -- generic crypto implementations +// + +#include "stdtwcrypto.h" +#include "crypto.h" +#include "core/archive.h" +#include "test/test.h" + +void TestCrypto() +{ + const int COUNT = 4000; + + const int BUFSIZE = 9000; + + char source[BUFSIZE]; + char crypt[COUNT + BUFSIZE]; // needs to be able to hold even number of blocks + char dest[COUNT]; + + memcpy(source, "I love the smell of the sheep.", 31); + + +#ifdef _IDEA_ENCRYPTION + /////////////////////////////////////////////////////////////////////////// + // IDEA test + { + memset(crypt, 0, COUNT + 1024); + memset(dest, 0, COUNT); + + cIDEA crypter; + + // we use buf for when the end of the source doesn't fall on a + // blocksize boundry. + TEST(crypter.GetBlockSizePlain() < 32); + TEST(crypter.GetBlockSizeCipher() < 32); + char buf[32]; + + // encrypt the phrase + crypter.SetKey(iCipher::ENCRYPT, cHashedKey128(_T("big cow"))); + + int i, j; + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + memcpy(buf, source + i, COUNT - i); + memset(buf + COUNT - i, 0, crypter.GetBlockSizePlain() - COUNT + i); + crypter.ProcessBlock(buf, crypt + j); + break; + } + + crypter.ProcessBlock(source + i, crypt + j); + } + + // dycrypt the phrase + crypter.SetKey(iCipher::DECRYPT, cHashedKey128(_T("big cow"))); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + } +#endif + +#ifdef _RSA_ENCRYPTION + /////////////////////////////////////////////////////////////////////////// + // RSA test + { + int i, j; + + memset(crypt, 0, COUNT + 1024); + memset(dest, 0, COUNT); + + cRSA crypter(cRSA::KEY2048); + + // we use buf for when the end of the source doesn't fall on a + // blocksize boundry. + TEST(crypter.GetBlockSizePlain() < BUFSIZE); + TEST(crypter.GetBlockSizeCipher() < BUFSIZE); + char buf[BUFSIZE]; + + cRSAPublicKey* pPublic; + cRSAPrivateKey* pPrivate; + + crypter.GenerateKeys(pPrivate, pPublic); + + // save the keys to a data stream and read back in + cRSAPublicKey* pPublic2; + cRSAPrivateKey* pPrivate2; + + ASSERT(pPublic->GetWriteLen() < BUFSIZE); + pPublic->Write(buf); + pPublic2 = new cRSAPublicKey(buf); + + ASSERT(pPrivate->GetWriteLen() < BUFSIZE); + pPrivate->Write(buf); + pPrivate2 = new cRSAPrivateKey(buf); + + // we will try encrypting to a second pair of buffers and see if all goes well + char crypt2[COUNT + BUFSIZE]; + char dest2[COUNT]; + + // encrypt the phrase + crypter.SetEncrypting(pPublic); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + memcpy(buf, source + i, COUNT - i); + memset(buf + COUNT - i, 0, crypter.GetBlockSizePlain() - COUNT + i); + crypter.ProcessBlock(buf, crypt + j); + break; + } + + crypter.ProcessBlock(source + i, crypt + j); + } + + crypter.SetEncrypting(pPublic2); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + memcpy(buf, source + i, COUNT - i); + memset(buf + COUNT - i, 0, crypter.GetBlockSizePlain() - COUNT + i); + crypter.ProcessBlock(buf, crypt2 + j); + break; + } + + crypter.ProcessBlock(source + i, crypt2 + j); + } + + // You might think this test would be valid (I did), but it is not. + // The Crypto++ lib pads input with random bytes so encrypting the + // same plaintext twice will not create the same ciphertext. + //TEST(memcmp(crypt, crypt2, crypter.GetBlockSizeCipher()) == 0); + + // dycrypt the phrase + crypter.SetDecrypting(pPrivate); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + + crypter.SetDecrypting(pPrivate2); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt2 + j, buf); + memcpy(dest2 + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt2 + j, dest2 + i); + } + + TEST(memcmp(source, dest2, COUNT) == 0); + TEST(memcmp(dest, dest2, COUNT) == 0); + + // zero out things and try signing and verifying + memset(crypt, 0, COUNT + 1024); + memset(dest, 0, COUNT); + + // sign the phrase + crypter.SetSigning(pPrivate); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + memcpy(buf, source + i, COUNT - i); + memset(buf + COUNT - i, 0, crypter.GetBlockSizePlain() - COUNT + i); + crypter.ProcessBlock(buf, crypt + j); + break; + } + + crypter.ProcessBlock(source + i, crypt + j); + } + + // verify the phrase + crypter.SetVerifying(pPublic); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + + // verify the phrase again using a local public key + cRSAPublicKey publicKey(*pPrivate); + crypter.SetVerifying(&publicKey); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + + delete pPublic; + delete pPrivate; + } +#endif + + + /////////////////////////////////////////////////////////////////////////// + // El Gamal test + { + int i, j; + + TCOUT << _T("El Gamal test\n"); + + memset(crypt, 0, COUNT + 1024); + memset(dest, 0, COUNT); + + cElGamalSig crypter(cElGamalSig::KEY512); + + // we use buf for when the end of the source doesn't fall on a + // blocksize boundry. + TEST(crypter.GetBlockSizePlain() < BUFSIZE); + TEST(crypter.GetBlockSizeCipher() < BUFSIZE); + char buf[BUFSIZE]; + + cElGamalSigPublicKey* pPublic; + cElGamalSigPrivateKey* pPrivate; + + crypter.GenerateKeys(pPrivate, pPublic); + + // save the keys to a data stream and read back in + cElGamalSigPublicKey* pPublic2; + cElGamalSigPrivateKey* pPrivate2; + + ASSERT(pPublic->GetWriteLen() < BUFSIZE); + pPublic->Write(buf); + pPublic2 = new cElGamalSigPublicKey(buf); + + ASSERT(pPrivate->GetWriteLen() < BUFSIZE); + pPrivate->Write(buf); + pPrivate2 = new cElGamalSigPrivateKey(buf); + + // we will try encrypting to a second pair of buffers and see if all goes well + //char crypt2[COUNT + BUFSIZE]; + //char dest2[COUNT]; + + // zero out things and try signing and verifying + memset(crypt, 0, COUNT + 1024); + memset(dest, 0, COUNT); + + TCOUT << _T("El Gamal Signing...\n"); + + // sign the phrase + crypter.SetSigning(pPrivate); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + memcpy(buf, source + i, COUNT - i); + memset(buf + COUNT - i, 0, crypter.GetBlockSizePlain() - COUNT + i); + crypter.ProcessBlock(buf, crypt + j); + break; + } + + crypter.ProcessBlock(source + i, crypt + j); + } + + TCOUT << _T("El Gamal Verifying...\n"); + + // verify the phrase + crypter.SetVerifying(pPublic); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + + TCOUT << _T("El Gamal Verifying with serialized key...\n"); + + // verify the phrase again using a local public key + cElGamalSigPublicKey publicKey(*pPrivate); + crypter.SetVerifying(&publicKey); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + + TCOUT << _T("El Gamal Testing altered buffer...\n"); + + try + { + crypt[4] = '\x42'; + + // verify the phrase again using a local public key + cElGamalSigPublicKey publicKey(*pPrivate); + crypter.SetVerifying(&publicKey); + + for (i = 0, j = 0; ; i += crypter.GetBlockSizePlain(), j += crypter.GetBlockSizeCipher()) + { + if (i + crypter.GetBlockSizePlain() > COUNT) + { + crypter.ProcessBlock(crypt + j, buf); + memcpy(dest + i, buf, COUNT - i); + break; + } + + crypter.ProcessBlock(crypt + j, dest + i); + } + + TEST(memcmp(source, dest, COUNT) == 0); + } + catch (eArchiveCrypto&) + { + // accept eArchiveCrypto + } + catch (eArchive&) + { + TCOUT << _T("Modified Buffer Test failed!\n"); + TEST(false); + } + + delete pPublic; + delete pPrivate; + } +} + diff --git a/src/twcrypto/keyfile.cpp b/src/twcrypto/keyfile.cpp new file mode 100644 index 0000000..f749e2e --- /dev/null +++ b/src/twcrypto/keyfile.cpp @@ -0,0 +1,580 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// keyfile.cpp + +#include "stdtwcrypto.h" + +#include "keyfile.h" +#include "crypto.h" +#include "core/archive.h" +#include "core/debug.h" +#include "core/fileheader.h" +#include "core/serializerimpl.h" + +// A magic number to identify key files +// I just picked this at random (I took the current time (14:34) squared it, +// converted it to hex and xor'ed with 0xffffffff, just in case you are wondering) - dmb +const uint32 KEY_MAGIC_NUMBER = 0xffe09f5b; +static const uint32 CURRENT_FIXED_VERSION = 0x02020000; +static const uint32 TW_21_VERSION = 0x02010000; + +/////////////////////////////////////////////////////////////////////////////// +// class cKeyFile + +cKeyFile::cKeyFile() +{ + mpPrivateKeyMem = 0; + mPrivateKeyMemLen = 0; + mpPrivateKey = 0; + mpPublicKey = 0; + mPrivateKeyUseCount = 0; +} + +cKeyFile::~cKeyFile() +{ + ReleaseMem(); +} + +void cKeyFile::ReleaseMem() +{ + //ASSERT(mPrivateKeyUseCount == 0); // though not an error, you should have called RealeasePrivateKey + + delete [] mpPrivateKeyMem; + delete mpPrivateKey; + delete mpPublicKey; + mpPrivateKeyMem = 0; + mPrivateKeyMemLen = 0; + mpPrivateKey = 0; + mpPublicKey = 0; + mPrivateKeyUseCount = 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetFileHeaderID() +/////////////////////////////////////////////////////////////////////////////// + +struct cKeyFileFHID { + cFileHeaderID* KeyFileID; + + cKeyFileFHID() { KeyFileID = 0; } + ~cKeyFileFHID() { delete KeyFileID; } +} gKeyFileFHID; + +const cFileHeaderID& cKeyFile::GetFileHeaderID() +{ + if (gKeyFileFHID.KeyFileID == 0) + gKeyFileFHID.KeyFileID = new cFileHeaderID(_T("cKeyFile")); + + // sanity check + ASSERT(*gKeyFileFHID.KeyFileID == cFileHeaderID(_T("cKeyFile"))); + + return *gKeyFileFHID.KeyFileID; +} + +bool cKeyFile::KeysLoaded() const +{ + ASSERT(mpPrivateKeyMem == 0 || mpPublicKey != 0); + + return (mpPrivateKeyMem != 0); +} + +// Read and write keys to a keyfile + +void cKeyFile::ReadFile(const TCHAR* filename) // throw eKeyFile() +{ + ReleaseMem(); + + int16 len; + + try + { + cFileArchive inFile; + cFileHeader fileHeader; + + inFile.OpenRead(filename); + + try + { + cSerializerImpl fhSer(inFile, cSerializerImpl::S_READ, filename); + fileHeader.Read(&fhSer); + } + catch (eError&) + { + throw eKeyFileInvalidFmt(); + } + + // check id and version + if (fileHeader.GetID() != cKeyFile::GetFileHeaderID()) + { + ASSERT(false); + throw eKeyFileInvalidFmt(); + } + + // NOTE:mdb 20 July 99 -- I changed this so that we can load both tw22 and + // tw21 key files, since their formatting is exactly the same besides + // the version number. + // + if( (fileHeader.GetVersion() != CURRENT_FIXED_VERSION) && + (fileHeader.GetVersion() != TW_21_VERSION) ) + { + ASSERT(false); + throw eKeyFileInvalidFmt(); + } + + // read public key + inFile.ReadInt16(len); + if (len <= 0 || len >= 9000) + { + ASSERT(false); + throw eKeyFileInvalidFmt(); + } + + int8* publicMem = new int8[len]; + if (inFile.ReadBlob(publicMem, len) != len) + { + ASSERT(false); + delete [] publicMem; + throw eKeyFileInvalidFmt(); + } + + mpPublicKey = new cElGamalSigPublicKey(publicMem); + delete [] publicMem; + + // read private key; + inFile.ReadInt16(len); + if (len <= 0 || len > 9000) + { + ASSERT(false); + delete mpPublicKey; + mpPublicKey = 0; + throw eKeyFileInvalidFmt(); + } + + mPrivateKeyMemLen = len; + mpPrivateKeyMem = new int8[len]; + if (inFile.ReadBlob(mpPrivateKeyMem, mPrivateKeyMemLen) < mPrivateKeyMemLen) + { + ASSERT(false); + delete mpPublicKey; + delete [] mpPrivateKeyMem; + mpPublicKey = 0; + mpPrivateKeyMem = 0; + mPrivateKeyMemLen = 0; + throw eKeyFileInvalidFmt(); + } + } + catch(eArchive&) + { + delete mpPublicKey; + delete [] mpPrivateKeyMem; + mpPublicKey = 0; + mpPrivateKeyMem = 0; + mPrivateKeyMemLen = 0; + throw eKeyFileArchive(filename); + } + catch(eKeyFile&) + { + throw; + } +} + +void cKeyFile::WriteFile(const TCHAR* filename) const // throw eKeyFile() +{ + ASSERT(KeysLoaded()); + + try + { + cFileArchive outFile; + cFileHeader fileHeader; + + outFile.OpenReadWrite(filename); + + fileHeader.SetID(cKeyFile::GetFileHeaderID()); + + // Set file version. + // If we in the future we wish to support reading keys different versions, + // we will have to move this + fileHeader.SetVersion(CURRENT_FIXED_VERSION); + + fileHeader.SetEncoding(cFileHeader::NO_ENCODING); + + { + cSerializerImpl fhSer(outFile, cSerializerImpl::S_WRITE, filename); + fileHeader.Write(&fhSer); + } + + // save public key + int16 len = mpPublicKey->GetWriteLen(); + int8* publicMem = new int8[len]; + mpPublicKey->Write(publicMem); + + outFile.WriteInt16(len); + outFile.WriteBlob(publicMem, len); + + delete [] publicMem; + + // save private key + len = mPrivateKeyMemLen; + outFile.WriteInt16(len); + outFile.WriteBlob(mpPrivateKeyMem, mPrivateKeyMemLen); + } + catch(eArchive&) + { + throw eKeyFileArchive(filename); + } +} + +// Functions to read and write the key to memory. GetWriteLen() will throw an +// exception if keys are not currently loaded. + +void cKeyFile::ReadMem(const int8* pMem) // throw eKeyFile() +{ + int16 i16; + int32 i32; + + ReleaseMem(); + + memcpy(&i32, pMem, sizeof(i32)); + if ((unsigned int)tw_ntohl(i32) != KEY_MAGIC_NUMBER) + throw eKeyFileInvalidFmt(); + pMem += sizeof(int32); + + memcpy(&i32, pMem, sizeof(i32)); + if (tw_ntohl(i32) != 1) // version check + throw eKeyFileInvalidFmt(); + pMem += sizeof(int32); + + memcpy(&i16, pMem, sizeof(i16)); + int16 len = tw_ntohs(i16); + if (len <= 0 || len > 9000) + { + ASSERT(false); + throw eKeyFileInvalidFmt(); + } + + mpPublicKey = new cElGamalSigPublicKey((void*)(pMem + sizeof(int16))); + pMem += sizeof(int16) + len; + + memcpy(&i16, pMem, sizeof(i16)); + mPrivateKeyMemLen = tw_ntohs(i16); + if (mPrivateKeyMemLen <= 0 || mPrivateKeyMemLen > 9000) + { + ASSERT(false); + delete mpPublicKey; + mpPublicKey = 0; + throw eKeyFileInvalidFmt(); + } + + mpPrivateKeyMem = new int8[mPrivateKeyMemLen]; + memcpy(mpPrivateKeyMem, pMem + sizeof(int16), mPrivateKeyMemLen); +} + +void cKeyFile::WriteMem(int8* pMem) const // throw eKeyFile() +{ + int16 i16; + int32 i32; + + if (!KeysLoaded()) + { + ASSERT(false); + throw eKeyFileUninitialized(_T("cKeyFile not initialized")); + } + + // magic number and version + i32 = tw_htonl(KEY_MAGIC_NUMBER); + memcpy(pMem, &i32, sizeof(i32)); + pMem += sizeof(int32); + + i32 = tw_htonl(1); + memcpy(pMem, &i32, sizeof(i32)); + pMem += sizeof(int32); + + // save public key + int16 len = mpPublicKey->GetWriteLen(); + i16 = tw_htons(len); + memcpy(pMem, &i16, sizeof(i16)); + pMem += sizeof(int16); + + mpPublicKey->Write(pMem); + pMem += len; + + // save private key + len = mPrivateKeyMemLen; + i16 = tw_htons(len); + memcpy(pMem, &i16, sizeof(i16)); + pMem += sizeof(int16); + + memcpy(pMem, mpPrivateKeyMem, mPrivateKeyMemLen); +} + +int cKeyFile::GetWriteLen() // throw eKeyFile() +{ + if (!KeysLoaded()) + { + ASSERT(false); + throw eKeyFileUninitialized(_T("cKeyFile not initialized")); + } + + return sizeof(int32) + // the magic number + sizeof(int32) + // version + sizeof(int16) + // sizeof public key + mpPublicKey->GetWriteLen() + // the public key + sizeof(int16) + // sizeof private key + mPrivateKeyMemLen; // the private key +} + +void cKeyFile::ProtectKeys(int8* passphrase, int passphraseLen) // throw eKeyFile() +{ + int i; + int16 i16; + + // generate the hash value of the private key + int len = mpPrivateKey->GetWriteLen(); + int8* privateKeyBits = new int8[len]; + mpPrivateKey->Write(privateKeyBits); + cHashedKey128 privateHash(privateKeyBits, len); + RandomizeBytes(privateKeyBits, len); + delete [] privateKeyBits; + + // generate cipher for encrypting private key + cHashedKey192 desKey(passphrase, passphraseLen); + cTripleDES des; + des.SetKey(iCipher::ENCRYPT, desKey); + + ASSERT(des.GetBlockSizeCipher() == des.GetBlockSizePlain()); + + // calculate size of the memory image of the private key + mPrivateKeyMemLen = cHashedKey128::GetWriteLen() + sizeof(int16) + mpPrivateKey->GetWriteLen(); + mPrivateKeyMemLen = (mPrivateKeyMemLen / des.GetBlockSizePlain() + 1) * des.GetBlockSizePlain(); + int sluff = mPrivateKeyMemLen - cHashedKey128::GetWriteLen() - sizeof(int16) - mpPrivateKey->GetWriteLen(); + + // write the hash of the private key, the size of the private key, and the private key, + // all as plaintext. + mpPrivateKeyMem = new int8[mPrivateKeyMemLen]; + privateHash.Write(mpPrivateKeyMem); + i16 = tw_htons(mpPrivateKey->GetWriteLen()); + memcpy(mpPrivateKeyMem + cHashedKey128::GetWriteLen(), &i16, sizeof(i16)); + mpPrivateKey->Write(mpPrivateKeyMem + cHashedKey128::GetWriteLen() + sizeof(int16)); + + RandomizeBytes(mpPrivateKeyMem + mPrivateKeyMemLen - sluff, sluff); + + // delete the private key + delete mpPrivateKey; + mpPrivateKey = 0; + + // encrypt the plaintext + for (i = 0; i < mPrivateKeyMemLen; i += des.GetBlockSizePlain()) + { + des.ProcessBlock(mpPrivateKeyMem + i, mpPrivateKeyMem + i); + } + +#ifdef _DEBUG + // try decoding it just to see if it worked + if (GetPrivateKey(passphrase, passphraseLen) == 0) + { + throw eKeyFileInvalidFmt(); + } + + ReleasePrivateKey(); +#endif + + RandomizeBytes(passphrase, passphraseLen); +} + +// Generate new keys + +void cKeyFile::GenerateKeys(int keySize, int8* passphrase, int passphraseLen) // throw eKeyFile() +{ + ReleaseMem(); + + cElGamalSig rsa((cElGamalSig::KeySize)keySize); + + // generate both keys + rsa.GenerateKeys(mpPrivateKey, mpPublicKey); + + ProtectKeys(passphrase, passphraseLen); +} + +void cKeyFile::ChangePassphrase(int8* passphraseOld, int passphraseOldLen, int8* passphrase, int passphraseLen) // throw eKeyFile() +{ + if (GetPrivateKey(passphraseOld, passphraseOldLen) == 0) + { + throw eKeyFileInvalidFmt(); + } + + ProtectKeys(passphrase, passphraseLen); +} + +// Access to the private key. Key is normally stored encrypted for safety. Call +// ReleasePrivateKey() to destory the plaintext version of the key as soon as you +// are done using the key. + +const cElGamalSigPrivateKey* cKeyFile::GetPrivateKey(int8* passphrase, int passphraseLen) +{ + int16 i16; + + if (!KeysLoaded()) + { + ASSERT(false); + throw eKeyFileUninitialized(_T("cKeyFile not initialized")); + } + + ASSERT(mPrivateKeyUseCount >= 0); + + if (mPrivateKeyUseCount == 0) + { + // generate cipher for decrypting private key + cHashedKey192 desKey(passphrase, passphraseLen); + cTripleDES des; + des.SetKey(iCipher::DECRYPT, desKey); + + ASSERT(des.GetBlockSizeCipher() == des.GetBlockSizePlain()); + + // get a copy of the ciphertext and decrypt it + int8* plainPrivateKeyMem = new int8[mPrivateKeyMemLen]; + memcpy(plainPrivateKeyMem, mpPrivateKeyMem, mPrivateKeyMemLen); + + ASSERT(mPrivateKeyMemLen % des.GetBlockSizePlain() == 0); + + int i; + for (i = 0; i < mPrivateKeyMemLen; i += des.GetBlockSizePlain()) + { + des.ProcessBlock(plainPrivateKeyMem + i, plainPrivateKeyMem + i); + } + + // calculate the hash on the private key + memcpy(&i16, plainPrivateKeyMem + cHashedKey128::GetWriteLen(), sizeof(i16)); + int len = tw_ntohs(i16); + + if (len + cHashedKey128::GetWriteLen() + sizeof(int16) > (unsigned int)mPrivateKeyMemLen) + { + RandomizeBytes(plainPrivateKeyMem, mPrivateKeyMemLen); + delete [] plainPrivateKeyMem; + RandomizeBytes(passphrase, passphraseLen); + return 0; + } + + cHashedKey128 privateHash(plainPrivateKeyMem + cHashedKey128::GetWriteLen() + sizeof(int16), len); + + // compare to the stored value + if (memcmp(plainPrivateKeyMem, privateHash.GetKey(), cHashedKey128::GetWriteLen()) != 0) + { + // passphrase didn't do the job + RandomizeBytes(plainPrivateKeyMem, mPrivateKeyMemLen); + delete [] plainPrivateKeyMem; + RandomizeBytes(passphrase, passphraseLen); + return 0; + } + + mpPrivateKey = new cElGamalSigPrivateKey(plainPrivateKeyMem + cHashedKey128::GetWriteLen() + sizeof(int16)); + + RandomizeBytes(plainPrivateKeyMem, mPrivateKeyMemLen); + delete [] plainPrivateKeyMem; + + RandomizeBytes(passphrase, passphraseLen); + } + else + { + // TODO: make sure the passphrase is correct + } + + ++mPrivateKeyUseCount; + return mpPrivateKey; +} + +void cKeyFile::ReleasePrivateKey() // throw eKeyFile() +{ + if (!KeysLoaded()) + { + ASSERT(false); + throw eKeyFileUninitialized(_T("cKeyFile not initialized")); + } + + ASSERT(mPrivateKeyUseCount > 0); + + if (--mPrivateKeyUseCount == 0) + { + delete mpPrivateKey; + mpPrivateKey = 0; + } +} + +const cElGamalSigPublicKey* cKeyFile::GetPublicKey() const // throw eKeyFile() +{ + if (!KeysLoaded()) + { + ASSERT(false); + throw eKeyFileUninitialized(_T("cKeyFile not initialized")); + } + + return mpPublicKey; +} + +/////////////////////////////////////////////////////////////////////////////// +// class cPrivateKeyProxy + +bool cPrivateKeyProxy::AquireKey(cKeyFile& keyFile, int8* passphrase, int passphraseLen) +{ + if (mpKey != 0) + { + ASSERT(mpKeyFile != 0); + mpKeyFile->ReleasePrivateKey(); + } + + mpKeyFile = &keyFile; + mpKey = keyFile.GetPrivateKey(passphrase, passphraseLen); + + return mpKey != 0; +} + +cPrivateKeyProxy::~cPrivateKeyProxy() +{ + if (mpKey != 0) + { + ASSERT(mpKeyFile != 0); + mpKeyFile->ReleasePrivateKey(); + } +} + +const cElGamalSigPrivateKey* cPrivateKeyProxy::GetKey() const // throw eKeyFile() +{ + if (mpKey == 0) + { + // This is a programming error + ASSERT(false); + throw eKeyFileUninitialized(_T("Private Key not initialized")); + } + + return mpKey; +} + diff --git a/src/twcrypto/keyfile.h b/src/twcrypto/keyfile.h new file mode 100644 index 0000000..c1a6c61 --- /dev/null +++ b/src/twcrypto/keyfile.h @@ -0,0 +1,151 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// keyfile.h + +#ifndef __KEYFILE_H +#define __KEYFILE_H + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +#ifndef __FILEERROR_H +#include "core/fileerror.h" +#endif + +class cElGamalSigPrivateKey; +class cElGamalSigPublicKey; +class cFileHeaderID; + +TSS_EXCEPTION( eKeyFile, eFileError ); +TSS_EXCEPTION( eKeyFileInvalidFmt, eKeyFile ); +TSS_EXCEPTION( eKeyFileBadPassphrase, eKeyFile ); +TSS_EXCEPTION( eKeyFileArchive, eKeyFile ); +TSS_EXCEPTION( eKeyFileUninitialized, eKeyFile ); + + +class cKeyFile +{ +public: + cKeyFile(); + ~cKeyFile(); + + void ReadFile(const TCHAR* filename); // throw eKeyFile() + void WriteFile(const TCHAR* filename) const; // throw eKeyFile() + // Read and write keys to a keyfile + + void ReadMem(const int8* pMem); // throw eKeyFile() + void WriteMem(int8* pMem) const; // throw eKeyFile() + int GetWriteLen(); // throw eKeyFile() + // Functions to read and write the key to memory. GetWriteLen() will throw an + // exception if keys are not currently loaded. + + bool KeysLoaded() const; + + void GenerateKeys(int keySize, int8* passphrase, int passphraseLen); // throw eKeyFile() + // Generate new keys + // Note: Bytes in passphrase will be cleared after keys are generated for safety + + void ChangePassphrase(int8* passphraseOld, int passphraseOldLen, int8* passphrase, int passphraseLen); // throw eKeyFile() + // Change passphrase + // Note: Bytes in passphrases will be cleared after change for safety + + const cElGamalSigPrivateKey* GetPrivateKey(int8* passphrase, int passphraseLen); + void ReleasePrivateKey(); + // Access to the private key. Key is normally stored encrypted for safety. Call + // ReleasePrivateKey() to destory the plaintext version of the key as soon as you + // are done using the key. + // Note: Bytes in passphrase will be cleared after keys are generated for safety + + const cElGamalSigPublicKey* GetPublicKey() const; + + static const cFileHeaderID& GetFileHeaderID(); + +protected: + int8* mpPrivateKeyMem; // encrypted version of private key + int mPrivateKeyMemLen; + + cElGamalSigPrivateKey* mpPrivateKey; // only valid between calls to GetPrivateKey() and ReleasePrivateKey() + cElGamalSigPublicKey* mpPublicKey; + + int mPrivateKeyUseCount; + +private: + void ProtectKeys(int8* passphrase, int passphraseLen); // throw eKeyFile() + void ReleaseMem(); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// class cPrivateKeyProxy +// +// Useful as a local var that releases the private key on destruction, thus +// a thrown exception will cause the key to be released propperly + +class cPrivateKeyProxy +{ +public: + cPrivateKeyProxy(); + ~cPrivateKeyProxy(); + + bool AquireKey(cKeyFile& keyFile, int8* passphrase, int passphraseLen); + // note: be sure to check return value for failure!!! + + bool Valid() const { return mpKey != 0; } + + const cElGamalSigPrivateKey* GetKey() const; + const cElGamalSigPrivateKey& operator ->() const { return *GetKey(); } + const cElGamalSigPrivateKey& operator *() const { return *GetKey(); } + // In all access to the key, an exception will be thrown + // if key has not been successfully aquired. +private: + cKeyFile* mpKeyFile; + const cElGamalSigPrivateKey* mpKey; +}; + +inline cPrivateKeyProxy::cPrivateKeyProxy() +: mpKeyFile(0), + mpKey(0) +{ +} + +#endif + diff --git a/src/twcrypto/keyfile_t.cpp b/src/twcrypto/keyfile_t.cpp new file mode 100644 index 0000000..7306e5c --- /dev/null +++ b/src/twcrypto/keyfile_t.cpp @@ -0,0 +1,135 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// keyfile_t.cpp +// + +#include "stdtwcrypto.h" +#include "keyfile.h" +#include "crypto.h" +#include "core/archive.h" +#include "core/debug.h" +#include "test/test.h" +#include "tw/twutil.h" + +//////////////////////////////////////////////////////////////////////////////// + +void TestKeyFile() +{ + cDebug d("TestKeyFile"); + + // test keyfile exceptions all work correctly + d.TraceDebug("Testing expception strings, IGNORE THESE ERRORS...\n"); + cTWUtil::PrintErrorMsg(eKeyFile(_T("Testing only, ignore this."))); + cTWUtil::PrintErrorMsg(eKeyFileInvalidFmt(_T("Testing only, ignore this."))); + cTWUtil::PrintErrorMsg(eKeyFileBadPassphrase(_T("Testing only, ignore this."))); + cTWUtil::PrintErrorMsg(eKeyFileArchive(_T("Testing only, ignore this."))); + cTWUtil::PrintErrorMsg(eKeyFileUninitialized(_T("Testing only, ignore this."))); + + cKeyFile keyfile; + + d.TraceDebug("Generating keys...\n"); + std::string s = "haybaby"; + keyfile.GenerateKeys(cElGamalSig::KEY1024, (int8*)s.data(), 7); + + char plaintext[9000]; + char ciphertext[9000]; + memset(plaintext, 42, 9000); + + // encrypt + d.TraceDebug("Encrypting...\n"); + { + cElGamalSig elGamal(*keyfile.GetPublicKey()); + + ASSERT(elGamal.GetBlockSizePlain() < 9000); + ASSERT(elGamal.GetBlockSizeCipher() < 9000); + std::string s = "haybaby"; + cPrivateKeyProxy key; + TEST(key.AquireKey(keyfile, (int8*)s.data(), 7)); + elGamal.SetSigning(key.GetKey()); + elGamal.ProcessBlock(plaintext, ciphertext); + } + + // decrypt + d.TraceDebug("Decrypting...\n"); + { + cElGamalSig elGamal(*keyfile.GetPublicKey()); + char recovered_text[9000]; + + elGamal.SetVerifying(keyfile.GetPublicKey()); + elGamal.ProcessBlock(ciphertext, recovered_text); + + TEST(memcmp(recovered_text, plaintext, elGamal.GetBlockSizePlain()) == 0); + } + + // save to and read from memory + d.TraceDebug("Read/Write to memory...\n"); + { + int8* pMem = new int8[keyfile.GetWriteLen()]; + keyfile.WriteMem(pMem); + + cKeyFile keyfile2; + TEST(!keyfile2.KeysLoaded()); + keyfile2.ReadMem(pMem); + TEST(keyfile2.KeysLoaded()); + + cElGamalSig elGamal(*keyfile2.GetPublicKey()); + char recovered_text[9000]; + + elGamal.SetVerifying(keyfile2.GetPublicKey()); + elGamal.ProcessBlock(ciphertext, recovered_text); + + TEST(memcmp(recovered_text, plaintext, elGamal.GetBlockSizePlain()) == 0); + } + + // save to and read from disk + d.TraceDebug("Read/Write to file...\n"); + { + keyfile.WriteFile(TEMP_DIR _T("/keyfile.key")); + + cKeyFile keyfile2; + TEST(!keyfile2.KeysLoaded()); + keyfile2.ReadFile(TEMP_DIR _T("/keyfile.key")); + TEST(keyfile2.KeysLoaded()); + + cElGamalSig elGamal(*keyfile2.GetPublicKey()); + char recovered_text[9000]; + + elGamal.SetVerifying(keyfile2.GetPublicKey()); + elGamal.ProcessBlock(ciphertext, recovered_text); + + TEST(memcmp(recovered_text, plaintext, elGamal.GetBlockSizePlain()) == 0); + } + + return; +} + diff --git a/src/twcrypto/stdtwcrypto.cpp b/src/twcrypto/stdtwcrypto.cpp new file mode 100644 index 0000000..b5a0e4b --- /dev/null +++ b/src/twcrypto/stdtwcrypto.cpp @@ -0,0 +1,41 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtwcrypto.cpp +// Date....: 5/12/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdtwcrypto.h" + + +// eof: stdtwcrypto.cpp diff --git a/src/twcrypto/stdtwcrypto.h b/src/twcrypto/stdtwcrypto.h new file mode 100644 index 0000000..70e0c55 --- /dev/null +++ b/src/twcrypto/stdtwcrypto.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtwcrypto.h +// +// Standard includes for twcrypto +// + +#include "core/stdcore.h" + diff --git a/src/twcrypto/twcrypto.cpp b/src/twcrypto/twcrypto.cpp new file mode 100644 index 0000000..ba4dba7 --- /dev/null +++ b/src/twcrypto/twcrypto.cpp @@ -0,0 +1,66 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twcrypto.cpp +// Date....: 05/12/99 +// Creator.: +// +// Implementation for the cTWCrypto package +// +// + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Dependencies +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "stdtwcrypto.h" // for: precompiled-header +#include "twcrypto.h" // for: cTWCrypto +#include "twcryptoerrors.h" + + +TSS_ImplementPackage( cTWCrypto ) + +//============================================================================= +// cTWCrypto::cTWCrypto() +//----------------------------------------------------------------------------- +// EFFECTS: +// +// POSTCONDITIONS: +// +// +cTWCrypto::cTWCrypto() +{ + TSS_REGISTER_PKG_ERRORS( twcrypto ) +} + +// eof: twcrypto.cpp diff --git a/src/twcrypto/twcrypto.h b/src/twcrypto/twcrypto.h new file mode 100644 index 0000000..f2df624 --- /dev/null +++ b/src/twcrypto/twcrypto.h @@ -0,0 +1,60 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twcrypto.h +// Date....: 05/12/99 +// Creator.: Brian McFeely (bmcfeely) +// +// TW crypto Package Class +// + +#ifndef __TWCRYPTO_H +#define __TWCRYPTO_H + + +//--Requirements + +#include "core/package.h" // for: TSS_DeclarePackage + +//--Classes + +TSS_BeginPackage( cTWCrypto ) + + public: + + cTWCrypto(); + +TSS_EndPackage( cTWCrypto ) + + +#endif//__TWCRYPTO_H + diff --git a/src/twcrypto/twcryptoerrors.cpp b/src/twcrypto/twcryptoerrors.cpp new file mode 100644 index 0000000..64cc046 --- /dev/null +++ b/src/twcrypto/twcryptoerrors.cpp @@ -0,0 +1,53 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// coreerrors.cpp +// +// Registers all error strings in the core package +// + +#include "stdtwcrypto.h" +#include "twcryptoerrors.h" + +#include "keyfile.h" + +TSS_BEGIN_ERROR_REGISTRATION( twcrypto ) + +// +// Keyfile +// +TSS_REGISTER_ERROR( eKeyFile(), _T("Unknown Keyfile error.") ); +TSS_REGISTER_ERROR( eKeyFileInvalidFmt(), _T("Invalid Keyfile format") ); +TSS_REGISTER_ERROR( eKeyFileBadPassphrase(), _T("Keyfile passphrase incorrect.") ); +TSS_REGISTER_ERROR( eKeyFileArchive(), _T("Keyfile Read/Write error.") ); +TSS_REGISTER_ERROR( eKeyFileUninitialized(), _T("Internal Keyfile error.") ); + +TSS_END_ERROR_REGISTRATION() diff --git a/src/twcrypto/twcryptoerrors.h b/src/twcrypto/twcryptoerrors.h new file mode 100644 index 0000000..149b9c3 --- /dev/null +++ b/src/twcrypto/twcryptoerrors.h @@ -0,0 +1,48 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twcryptoerrors.h +// Date....: 6/30/99 +// Creator.: daveb +// +// + +#ifndef __TWCRYPTOERRORS_H +#define __TWCRYPTOERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( twcrypto ) + + +#endif//__COREERRORS_H + diff --git a/src/twparser/Makefile.am b/src/twparser/Makefile.am new file mode 100644 index 0000000..138b838 --- /dev/null +++ b/src/twparser/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libtwparser.a +libtwparser_a_SOURCES = \ + genreparseinfo.cpp parserhelper.cpp parserobjects.cpp \ + policyparser.cpp stdtwparser.cpp twparser.cpp twparsererrors.cpp \ + twparserstrings.cpp yylex.cpp yyparse.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtwparser_a_OBJECTS) diff --git a/src/twparser/Makefile.in b/src/twparser/Makefile.in new file mode 100644 index 0000000..3bd0fcc --- /dev/null +++ b/src/twparser/Makefile.in @@ -0,0 +1,402 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libtwparser_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/twparser +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libtwparser_a_AR = $(AR) $(ARFLAGS) +libtwparser_a_LIBADD = +am_libtwparser_a_OBJECTS = genreparseinfo.$(OBJEXT) \ + parserhelper.$(OBJEXT) parserobjects.$(OBJEXT) \ + policyparser.$(OBJEXT) stdtwparser.$(OBJEXT) \ + twparser.$(OBJEXT) twparsererrors.$(OBJEXT) \ + twparserstrings.$(OBJEXT) yylex.$(OBJEXT) yyparse.$(OBJEXT) +libtwparser_a_OBJECTS = $(am_libtwparser_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libtwparser_a_SOURCES) +DIST_SOURCES = $(libtwparser_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libtwparser.a +libtwparser_a_SOURCES = \ + genreparseinfo.cpp parserhelper.cpp parserobjects.cpp \ + policyparser.cpp stdtwparser.cpp twparser.cpp twparsererrors.cpp \ + twparserstrings.cpp yylex.cpp yyparse.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/twparser/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/twparser/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libtwparser.a: $(libtwparser_a_OBJECTS) $(libtwparser_a_DEPENDENCIES) + -rm -f libtwparser.a + $(libtwparser_a_AR) libtwparser.a $(libtwparser_a_OBJECTS) $(libtwparser_a_LIBADD) + $(RANLIB) libtwparser.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libtwparser_a_OBJECTS) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/twparser/genreparseinfo.cpp b/src/twparser/genreparseinfo.cpp new file mode 100644 index 0000000..5b9a968 --- /dev/null +++ b/src/twparser/genreparseinfo.cpp @@ -0,0 +1,272 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreparseinfo.cpp -- helper classes that are called by yacc parser +// + +#include "stdtwparser.h" + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "parserhelper.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "fco/genreswitcher.h" +#include "fco/parsergenreutil.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +//========================================================================= +// DEFINES AND MACROS +//========================================================================= + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +//========================================================================= +// GLOBALS +//========================================================================= + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +//========================================================================= +// METHOD CODE +//========================================================================= + + +cGenreParseInfo::cGenreParseInfo() +{ + InitPredefinedVariables(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// AddStopPoint +// NOTE: the list copies the string, so it is safe for the parser to +// free the lexeme +/////////////////////////////////////////////////////////////////////////////// +void +cGenreParseInfo::AddStopPoint( const cFCOName& name ) +{ + mStopList.push_back( name ); +} + +/////////////////////////////////////////////////////////////////////////////// +// AddRule -- adds the specified rule to our list. we will eventually call +// MakeFCOSpecs(), which will use this list as its source. +// +// NOTE: the list is responsible for freeing the pointers +/////////////////////////////////////////////////////////////////////////////// +void +cGenreParseInfo::AddRule(const cParseRule *pnode) +{ + mRuleList.push_back(pnode); +} + +/////////////////////////////////////////////////////////////////////////////// +// RulePointAlreadyDefined -- returns true if the given name was already used +// as a start or stop point +/////////////////////////////////////////////////////////////////////////////// +bool cGenreParseInfo::RulePointAlreadyDefined( const cFCOName& fcoName ) +{ + bool fFound = false; + + // check start points + for( RuleListType::iterator i = mRuleList.begin(); i != mRuleList.end(); i++ ) + { + if( (*i)->GetName() == fcoName ) + fFound = true; + } + + // check stop points + if( ! fFound ) + { + for( StopListType::iterator j = mStopList.begin(); j != mStopList.end(); j++ ) + { + if( *j == fcoName ) + fFound = true; + } + } + + return( fFound ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// InitPredefinedVariables -- +/////////////////////////////////////////////////////////////////////////////// +void cGenreParseInfo::InitPredefinedVariables() +{ + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + + TSTRING sVarName, sValue; + int index = 0; + while( pGU->EnumPredefinedVariables( index++, sVarName, sValue ) ) + { + mLocalPredefVarTable.Insert( sVarName, sValue ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// DoVarSubstitution() +// replaces any $(VAR) in string with it's value, unless the $ is escaped with +// a backslash. Fails if symbol isn't found +/////////////////////////////////////////////////////////////////////////////// + +bool cGenreParseInfo::DoVarSubstitution( TSTRING &rval ) //throw( eParserHelper ) +{ + cDebug d("cConfigFile::DoVarSubst()"); + d.TraceDebug("ORIG: %s\n", rval.c_str()); + + // walk through string + // look for $( + // find matching ) + // pick out subset + // look up in symbol table + // substitute subset + // continue iterating + + // step through string + // iterate to (slen-1), because we are looking for a two-character sentinel "$(" + bool fEscaping = false; + for (TSTRING::size_type i = 0; i < rval.size(); i++) + { + TCHAR c = rval[i]; + + // is it the "$(" sentinel? (an escaped '$' is not a variable) + if (c == '$' && ! fEscaping ) + { + c = rval[i+1]; + if (c == '(') + { + // ooh, wow! it's a variable! find the end + bool found = false; + TSTRING::size_type j; + + for (j = i+1; j < rval.size(); j++) + { + if (rval[j] == ')') + { + found = true; + break; + } + } + + // did we find it? + if (!found) + { + // TODO: throw error + return false; + } + + // otherwise, cut out the variable name + TSTRING::size_type begin = i + 2; + TSTRING::size_type size = j - i - 2; + TSTRING varname; + varname = rval.substr(begin, size); + + d.TraceDebug("symbol = %s\n", varname.c_str()); + + // look up in symbol table + TSTRING varvalue; + if ( ! LookupVariable( varname, varvalue ) ) + throw eParserUseUndefVar( varname ); + + // replace varname with varvalue + rval.replace(begin-2, size+3, varvalue); + + d.TraceDebug("POST: %s\n", rval.c_str()); + + // no no no + // we should exit function, and get called again + + + // update counters + // we should bump the cursor over by the length of the + // varvalue (minus one, to compensate for post-increment of index) + i += varvalue.size() - 1; + goto nextchar; + } + } + else if (c == '\\') + { + fEscaping = ! fEscaping; + } + else + { + fEscaping = false; + } +nextchar: + ; + } + + + + d.TraceDebug("DONE: %s\n", rval.c_str()); + + // switch around + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Insert -- add definition to symbol table +/////////////////////////////////////////////////////////////////////////////// +bool cGenreParseInfo::InsertVariable( const TSTRING& var, const TSTRING& val ) //throw( eParserHelper ) +{ + TSTRING dummy; + // don't let them redefine predefined vars + if( mLocalPredefVarTable.Lookup(var, dummy) ) + throw eParserRedefineVar( var ); + + return mLocalVarTable.Insert( var, val ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Lookup -- returns value, or returns false +// This method will return false only if the given variable is not defined +// in any of the three symbol tables. +/////////////////////////////////////////////////////////////////////////////// +bool cGenreParseInfo::LookupVariable( const TSTRING& var, TSTRING& val ) +{ + if( mLocalPredefVarTable.Lookup( var, val ) || mLocalVarTable.Lookup( var, val ) ) + return true; + else + return ( cParserHelper::GetGlobalVarTable().Lookup( var, val ) ); +} diff --git a/src/twparser/genreparseinfo.h b/src/twparser/genreparseinfo.h new file mode 100644 index 0000000..cbb07eb --- /dev/null +++ b/src/twparser/genreparseinfo.h @@ -0,0 +1,132 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// genreparseinfo.h -- holds parsing information for each genre +// + +#ifndef __GENREPARSEINFO_H +#define __GENREPARSEINFO_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __ERROR_H +#include "core/error.h" +#endif + +#ifndef __HASHTABLE_H +#include "core/hashtable.h" +#endif + +#ifndef __PARSEROBJECTS_H +#include "parserobjects.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +class cSymbolTable +{ +public: + bool Insert( const TSTRING &var, const TSTRING &val ) { return mTable.Insert( var, val ); } + bool Lookup( const TSTRING &var, TSTRING &val ) { return mTable.Lookup( var, val ); } + +private: + cHashTable mTable; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// this class exists only to encapsulate the routines to help the parser +// along -- the goal is to reduce the code that lives in the yacc +// + +class cGenreParseInfo +{ +public: + cGenreParseInfo(); + + void AddStopPoint( const cFCOName& name ); + // adds the specified path as a stop point -- for now, we just queue it up, + // since we don't know which rule to attach it to. to do that, we call + // AttachStopPoints() + + bool RulePointAlreadyDefined( const cFCOName& fcoName ); + // checks if szName is in mSpecNameList + + void AddRule(const cParseRule *pnode); + // adds the specified rule to our list. we will eventually call CreateFCOSpecs(), + // which will use the list as its source. + + bool DoVarSubstitution(TSTRING &rval); //throw( eParserHelper ) + + bool InsertVariable( const TSTRING& var, const TSTRING& val); //throw( eParserHelper ) + bool LookupVariable( const TSTRING& var, TSTRING& val); + // This method now looks in the global variable table (defined in cParserHelper ), + // if a variable is not found in the local or predefined tables. + + // + // data retreval + // + typedef std::list< cFCOName > StopListType; + typedef std::list< const cParseRule* > RuleListType; + RuleListType* GetRules() { return &mRuleList; }; + StopListType* GetStopList() { return &mStopList; }; + + cSymbolTable& GetPredefVarTable( void ) { return mLocalPredefVarTable; } + +private: + void InitPredefinedVariables(); + + + + StopListType mStopList; + // this is where all the stop points are stored at parse-time, since we + // don't know enough to bind them to fcospecs yet. + + RuleListType mRuleList; + // these are the list of parser generated rules + + cSymbolTable mLocalVarTable; + // contains all the variable symbol definitions + cSymbolTable mLocalPredefVarTable; + // Contains the predefined variable definitions. +}; + +#endif // __GENREPARSEINFO_H + diff --git a/src/twparser/parserhelper.cpp b/src/twparser/parserhelper.cpp new file mode 100644 index 0000000..bb0b579 --- /dev/null +++ b/src/twparser/parserhelper.cpp @@ -0,0 +1,1204 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// parserhelper.cpp -- helper classes that are called by yacc parser +// + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +#include "stdtwparser.h" + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "parserhelper.h" +#include "core/fsservices.h" +#include "fco/fcopropvector.h" +#include "fco/parsergenreutil.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fcospechelper.h" +#include "core/twlimits.h" +#include "core/stringutil.h" + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +static int util_ConvertHex( const char* psz, int* const pnCharsRead ); +static int util_ConvertUnicode( const char* psz, int* const pnCharsRead ); +static int util_ConvertOctal( const char* psz, int* const pnCharsRead ); +static bool util_IsOctal( const char ch ); +static int util_GetEscapeValueOfChar( char ch ); +static int util_GetRecurseDepth( const cParseNamedAttrList* pList ); //throw( eParserHelper ) +static void util_EatAllSpaces( TSTRING& str ); +static void util_LoseSurroundingWS( TSTRING& str ); +#ifdef _DEBUG +static bool util_AsciiCharsActLikeTheyShould(); +#endif + +// finds first '&', '+', '-' on or after str[i] +static TSTRING::size_type util_FindNextDelim( const TSTRING& str, TSTRING::size_type i ); + + +//========================================================================= +// STATIC DATA MEMBERS +//========================================================================= + +cErrorBucket* cParserHelper::mpError; +int cParserHelper::miLineNum; +cPreprocessor::AcceptStack cPreprocessor::mStateStack; +bool cPreprocessor::mfIgnoreSection; + +cParserHelper::ScopedAttrContainer cParserHelper::mScopedAttrs; +cParserHelper::GenreContainer cParserHelper::mAph; +cGenreParseInfo* cParserHelper::pCurrentGenreInfo; +cSymbolTable cParserHelper::mGlobalVarTable; +bool cParserHelper::mfParseOnly; + + +//========================================================================= +// METHOD CODE +//========================================================================= + +eParserHelper::eParserHelper( const TSTRING& strMsg, int nLine /*= CURRENT_LINE */) +{ + TOSTRINGSTREAM strErr; + + strErr << strMsg; + + if( NO_LINE != nLine ) + { + // separate the message from the line number + if( ! strMsg.empty() ) + strErr << _T(": "); + + // output the line number + strErr << TSS_GetString( cTWParser, twparser::STR_LINE_NUMBER ); + + if( CURRENT_LINE == nLine ) + strErr << cParserHelper::GetLineNumber(); + else + strErr << nLine; + } + + mMsg = strErr.str(); +} + + +void cParserHelper::Init( cErrorBucket* pE ) +{ + // start off in default genre + cGenreSwitcher::GetInstance()->SelectGenre( cGenreSwitcher::GetInstance()->GetDefaultGenre() ); + + mpError = pE; + cPreprocessor::PushState( cPreprocessor::STATE_ACCEPT ); + miLineNum = 1; + cPreprocessor::ReadSection(); + pCurrentGenreInfo = NULL; + mfParseOnly = false; +} + +void cParserHelper::Finit( cGenreSpecListVector* pPolicy ) +{ + // + // don't build spec list if just checking syntax + // + if( ! pPolicy ) + { + CleanUp(); + return; + } + + int nRulesInPolicy = 0; + + GenreContainer::iterator i; + for( i = mAph.begin(); i != mAph.end(); i++ ) + { + cGenreSpecListPair slp; + cGenre::Genre g = i->first; + cGenreParseInfo* pgpi = i->second; + + // + // create the specs from rules + // + cParserUtil::CreateFCOSpecs( g, pgpi, slp.GetSpecList() ); + slp.SetGenre( g ); + + // + // get rule count for section + // + int nRulesInSection = slp.GetSpecList().Size(); + if( 0 == nRulesInSection ) + { + TSTRING str = TSS_GetString( cTWParser, twparser::STR_ERR2_PARSER_NO_RULES_IN_SECTION); + str.append( cGenreSwitcher::GetInstance()->GenreToString( slp.GetGenre(), true ) ); + + eParserNoRulesInSection e( str ); + e.SetFatality( false ); + cParserHelper::GetErrorBucket()->AddError( e ); + } + + // + // increment rule count for policy file + // + nRulesInPolicy += slp.GetSpecList().Size(); + + // + // add to policy + // + pPolicy->push_back( slp ); + } + + CleanUp(); + + // + // check that we have some rules + // + if( 0 == nRulesInPolicy ) + throw eParserNoRules( _T(""), eParserHelper::NO_LINE ); +} + +void cParserHelper::CleanUp() +{ + GenreContainer::iterator i; + for( i = mAph.begin(); i != mAph.end(); i++ ) + delete i->second; + while( ! cPreprocessor::Empty() ) + cPreprocessor::PopState(); + while( ! cParserHelper::ScopeEmpty() ) + cParserHelper::PopScope(); +} + +cPreprocessor::cPreprocessor() +{ + // start in the accept state + mStateStack.push( STATE_ACCEPT ); +} + +void cPreprocessor::PushState( AcceptState state ) +{ + mStateStack.push( state ); + + cDebug d("cPreprocessor::PushState"); + + if( state == STATE_ACCEPT ) + d.TraceDebug(_T("State == STATE_ACCEPT\n")); + else + d.TraceDebug(_T("State == STATE_IGNORE\n")); +} + +void cPreprocessor::PopState() +{ + cDebug d("cPreprocessor::PopState"); + + ASSERT( ! mStateStack.empty() ); + mStateStack.pop(); + +#ifdef _DEBUG + if( !Empty() && TopState() == STATE_ACCEPT ) + d.TraceDebug(_T("State == STATE_ACCEPT\n")); + else + d.TraceDebug(_T("State == STATE_IGNORE\n")); +#endif +} + +cPreprocessor::AcceptState cPreprocessor::GetState() +{ + if( STATE_ACCEPT == TopState() && false == mfIgnoreSection ) + return STATE_ACCEPT; + else + return STATE_IGNORE; +} + +cPreprocessor::AcceptState cPreprocessor::TopState() +{ + ASSERT( ! mStateStack.empty() ); + + return mStateStack.top(); +} + +cPreprocessor::AcceptState cPreprocessor::UnderneathTopState() +{ + ASSERT( mStateStack.size() > 1 ); + + AcceptState stateRet, stateSave; + + stateSave = mStateStack.top(); + mStateStack.pop(); + stateRet = mStateStack.top(); + mStateStack.push( stateSave ); + + return( stateRet ); +} + +void cPreprocessor::ToggleTopState() +{ + ASSERT( ! mStateStack.empty() ); + cDebug d("cPreprocessor::ToggleState"); + + AcceptState state = TopState(); + + mStateStack.pop(); + + // toggle state + mStateStack.push( GetOppositeState( state ) ); + + if( GetOppositeState( state ) == STATE_ACCEPT ) + d.TraceDebug(_T("State == STATE_ACCEPT\n")); + else + d.TraceDebug(_T("State == STATE_IGNORE\n")); +} + + +cPreprocessor::AcceptState cPreprocessor::GetOppositeState( AcceptState state ) +{ + if( state == STATE_IGNORE ) + return STATE_ACCEPT; + else + return STATE_IGNORE; +} + + +bool cPreprocessor::AtTopLevel() +{ + ASSERT( ! mStateStack.empty() ); + + bool fAtTop; + AcceptState stateSave; + + // save and pop current state + stateSave = mStateStack.top(); + mStateStack.pop(); + + // we're at top level if there was only one item in stack + fAtTop = mStateStack.empty(); + + // return item to stack + mStateStack.push( stateSave ); + + return( fAtTop ); +} + +// pushes cPreprocessor::STATE_IGNORE onto the state stack if +// strSection is not an acceptable genre for this OS + +void cParserHelper::SetSection( TSTRING& strSection ) // throw( eParserHelper ) +{ + // + // do we recognize the section string? + // + cGenre::Genre g = cGenreSwitcher::GetInstance()->StringToGenre( strSection.c_str() ); + if( cGenre::GENRE_INVALID != g && cGenreSwitcher::GetInstance()->IsGenreAppropriate( g ) ) + { + cGenreSwitcher::GetInstance()->SelectGenre( g ); + + // set current genre info pointer + GenreContainer::iterator i = mAph.find( cGenreSwitcher::GetInstance()->CurrentGenre() ); + if( mAph.end() == i ) + { + pCurrentGenreInfo = new cGenreParseInfo; + mAph.insert( GenreContainer::value_type( cGenreSwitcher::GetInstance()->CurrentGenre(), pCurrentGenreInfo ) ); + + cPreprocessor::ReadSection(); + } + else + { + throw eParserSectionAlreadyDefined( strSection ); + } + } + else // ignore + { + if( ! ParseOnly() ) + { + eParserIgnoringSection e( strSection ); + e.SetFatality( false ); + if( mpError ) mpError->AddError( e ); + } + + cPreprocessor::IgnoreSection(); + } +} + +// A function for inserting a global variable into the global variable table. Throws +// an exception if they try to redefine one of the predefined variables. Returns +// the return value of the hash table insert. +bool cParserHelper::InsertGlobalVariable( const TSTRING& var, const TSTRING& val ) +{ + TSTRING dummy; + /* if( cParserHelper::GetGenreInfo()->GetPredefVarTable().Lookup(var, dummy) ) + throw eParserRedefineVar( var ); + */ + // TODO : Verify that there is no feasible way to search the predefines without + // messing everything up, given our current architecture. + + return mGlobalVarTable.Insert( var, val ); +} + +cGenreParseInfo* cParserHelper::GetGenreInfo() +{ + if( ! pCurrentGenreInfo ) + { + pCurrentGenreInfo = new cGenreParseInfo; + mAph.insert( GenreContainer::value_type( cGenreSwitcher::GetInstance()->CurrentGenre(), pCurrentGenreInfo ) ); + } + + return pCurrentGenreInfo; +} + +bool cParserUtil::AnyOfTheseHostsExists( cParseStringList* pList ) +{ + TSTRING strHostName; + cDebug d("cPreprocessor::AnyOfTheseHostsExists"); + + // this throws an exception. let it go on up, since we can't do any ifhosting + // if we don't know what machine we're on + iFSServices::GetInstance()->GetMachineName( strHostName ); + + // want to do a case-insensitive compare + std::transform( strHostName.begin(), strHostName.end(), strHostName.begin(), _totlower ); + + // if the host name matches any in the list, return true + for( std::list::iterator iter = pList->begin(); iter != pList->end(); iter++ ) + { + // want to do case-insensitive compare + std::transform( (*iter).begin(), (*iter).end(), (*iter).begin(), _totlower ); + + if( 0 == strHostName.compare( (*iter) ) ) + { + d.TraceDebug(_T("host exists\n")); + return true; + } + } + + d.TraceDebug(_T("host doesn't exist\n")); + return false; +} + +// converts escaped character sequences in strEscapedString into their escape characters in strInterpretedString +//( e.g. turns "Hello World!\n" (literal backslash) into "Hello World!" +// all C++ escape sequences are recognized: +// (1) octal numbers \012 (1, 2, or 3 octal digits), +// (2) hex numbers \x2A ( 'x' followed by one or two hex digits ), +// (3) unicode characters \uABCD ( 'u' followed by exactly 4 hex digits ) +// (4) chars: \t, \v, \b, \r, \f, \a, \\, \?, \', and \" +// (5) all other escaped chars are treated as if not escaped +void cParserUtil::InterpretEscapedString( const std::string& strEscapedString, TSTRING& strInterpretedString ) +{ + cDebug d("cParserHelper::InterpretEscapedString"); + + ASSERT( (void*)&strEscapedString != (void*)&strInterpretedString ); // don't let us read and write to same string + + // The source string may contain literal multibyte characters, escaped MB characters, and escaped Unicode characters. + // On Unix TCHAR == char always, therefore literal and esacped mb chars can be stored in strInterpretedString + // directly, and everythign will be hunky dory (escased Unicode will cause an error). + // But on Windows we need to build an intermediate narrow string because it needs to be passed through + // cStringUtil::StrToTstr() to convert literal and escaped mb chars to TCHARs (which are wchar_t in this case). + // Escaped Unicode chars are included in this intermediate string specially encoded so that StrToTstr() + // leaves it alone. After we have the wide string, we convert these encoded Unicode chars into true 16 bit + // Unicode chars. + + #ifdef _UNICODE + typedef char INTERCHAR; + const char unicodeEscape = '\x01'; // This value must be chosen carefully so not to conflict with escape chars or mb chars + const char unicodeBase = 'A'; // This value must not fool the convertion from single to multibyte + bool unicodeWasEscaped = false; + std::string strIntermediateString; + #else + // for unix we cheat a bit and do the initial interpretation + // directly to the final string. + typedef TCHAR INTERCHAR; + TSTRING& strIntermediateString = strInterpretedString; + #endif + + const char* pchCur = strEscapedString.c_str(); + + for( strIntermediateString.erase(); + *pchCur != 0; + pchCur++ ) // only single byte in this part of the policy file + { + if( *pchCur != '\\' ) // just regular char + { + #ifdef _UNICODE + // check for our special unicode escape char, and escape it if necessary + if ( *pchCur == unicodeEscape ) + { + strIntermediateString += unicodeEscape; + unicodeWasEscaped = true; + } + #endif + + strIntermediateString += *pchCur; + } + else // deal with escaped character sequence + { + // make sure the '\' isn't the end of the string + // ( if it is, the "for" will ++ pchCur, see it's 0, then break ) + if( *(pchCur + 1 ) ) + { + int nCharsRead; + + pchCur++; // go to char past '\' + + if (*pchCur == 'x' && std::isxdigit(*(pchCur+1), std::locale() ) ) // deal with \xXXXX where 'x' is the character 'x', and 'X' is a hex number + { + pchCur++; // go to char past 'x' + char cEscapedChar = static_cast( util_ConvertHex( pchCur, &nCharsRead ) ); + pchCur += ( nCharsRead == 0 ) ? 0 : nCharsRead - 1; //increment pointer to last char we read + + if (cEscapedChar == 0) // null characters are not allowed + { + throw eParserBadHex( cStringUtil::StrToTstr( pchCur - (( nCharsRead == 0 ) ? 0 : nCharsRead - 1) ) ); + } + else + { + strIntermediateString += static_cast(cEscapedChar); + } + } + else if (*pchCur == 'u') // unicode escape + { + pchCur++; // go to char past 'x' + wchar_t wcEscapedChar = static_cast( util_ConvertUnicode( pchCur, &nCharsRead ) ); + pchCur += ( nCharsRead == 0 ) ? 0 : nCharsRead - 1; //increment pointer to last char we read + + if (wcEscapedChar == 0) // null characters are not allowed + { + throw eParserBadHex( cStringUtil::StrToTstr( pchCur - (( nCharsRead == 0 ) ? 0 : nCharsRead - 1) ) ); + } + + // For non-unicode Unix, we don't support > 0xff characters. + // Unicode Windows supports it just fine. + #ifndef _UNICODE + else if (wcEscapedChar > 0xff) + { + throw eParserBadHex( cStringUtil::StrToTstr( pchCur - (( nCharsRead == 0 ) ? 0 : nCharsRead - 1) ) ); + } + else + { + strIntermediateString += static_cast(wcEscapedChar); + } + #else + else if (wcEscapedChar <= 0xff) + { + strIntermediateString += static_cast(wcEscapedChar); + } + else + { + strIntermediateString += unicodeEscape; + strIntermediateString += static_cast((wcEscapedChar >> 12 & 0xf) + unicodeBase); + strIntermediateString += static_cast((wcEscapedChar >> 8 & 0xf) + unicodeBase); + strIntermediateString += static_cast((wcEscapedChar >> 4 & 0xf) + unicodeBase); + strIntermediateString += static_cast((wcEscapedChar & 0xf) + unicodeBase); + unicodeWasEscaped = true; + } + #endif + } + else if( util_IsOctal( *pchCur ) ) // deal with \xxx where 'x' is an octal digit + { + strIntermediateString += static_cast( util_ConvertOctal( pchCur, &nCharsRead ) ); + pchCur += ( nCharsRead == 0 ) ? 0 : nCharsRead - 1; //increment pointer to last char we read + } + else // deal with \x where 'x' is any other character + { + strIntermediateString += static_cast( util_GetEscapeValueOfChar( *pchCur ) ); + } + } + } + } + + #ifdef _UNICODE + // now convert to the wide vertion + strInterpretedString = cStringUtil::StrToTstr(strIntermediateString); + + // search for unicode escapes + if (unicodeWasEscaped) + { + TSTRING::iterator i; + for (i = strInterpretedString.begin(); i != strInterpretedString.end(); ++i) + { + if (*i == static_cast(unicodeEscape)) + { + i = strInterpretedString.erase(i); + ASSERT(i != strInterpretedString.end()); // This would indicate a logic error above + + if (*i != static_cast(unicodeEscape)) // check that this is escaped unicode + { + wchar_t wc; + TSTRING::iterator j = i; + + ASSERT(*j >= unicodeBase && *j < unicodeBase + 16); + wc = static_cast((*j++ - unicodeBase) << 12); + ASSERT(j != strInterpretedString.end()); + + ASSERT(*j >= unicodeBase && *j < unicodeBase + 16); + wc |= static_cast((*j++ - unicodeBase) << 8); + ASSERT(j != strInterpretedString.end()); + + ASSERT(*j >= unicodeBase && *j < unicodeBase + 16); + wc |= static_cast((*j++ - unicodeBase) << 4); + ASSERT(j != strInterpretedString.end()); + + ASSERT(*j >= unicodeBase && *j < unicodeBase + 16); + wc |= static_cast((*j++ - unicodeBase)); + i = strInterpretedString.erase(i, j); + i = strInterpretedString.insert(i, wc); + } + } + } + } + #endif + +#ifdef _DEBUG + std::string str; + + str = "before: <"; + str += strEscapedString; + str += ">\n"; + d.TraceDebug( str.c_str() ); + + TSTRING tstr; + tstr = _T("after: <"); + tstr += strInterpretedString; + tstr += _T(">\n"); + d.TraceDebug( tstr.c_str() ); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// CreateFCOSpecs -- foreach rule, create an FCOSpec. then attach the stop +// points. +/////////////////////////////////////////////////////////////////////////////// +void cParserUtil::CreateFCOSpecs( cGenre::Genre g, cGenreParseInfo* pgpi, cFCOSpecList &fcospeclist) //throw( eParserHelper ) +{ + cGenreSwitcher::GetInstance()->SelectGenre( g ); + iParserGenreUtil* pHelper = iTWFactory::GetInstance()->CreateParserGenreUtil(); + + cDebug d("cGenreParseInfo::CreateFCOSpecs"); + + // foreach rule + std::list::iterator rule; + for (rule = pgpi->GetRules()->begin(); rule != pgpi->GetRules()->end(); rule++) + { + // + // create the spec with its the last element of its start point as its name. + // if the attribute 'rulename' is specified, we'll set it as the spec name later + // Need to set the start point after the helper is set + // + cFCOName startpoint = (*rule)->GetName(); + iFCOSpec *pfcospec = iTWFactory::GetInstance()->CreateSpec( startpoint.GetShortName() ); // we'll set the helper below + + ////////////////////////////////////////////////////////////// + // look to see if no recurse was specified. if it is, set the helper to a cFCOSpecNoChildren, + // otherwise set it to a cFCOSpecStopPointSet + int depth = util_GetRecurseDepth( (*rule)->GetAttrList() ); + if( 0 == depth ) + { + // don't use stop point set. say don't recurse + cFCOSpecNoChildren* pNoKids = new cFCOSpecNoChildren; + pfcospec->SetHelper( pNoKids ); + } + else + { + cFCOSpecStopPointSet* pStopPtSet = new cFCOSpecStopPointSet; + + // set stop points + cGenreParseInfo::StopListType::iterator stop; + for (stop = pgpi->GetStopList()->begin(); stop != pgpi->GetStopList()->end(); stop++) + { + // add stop point if below start point + cFCOName::Relationship relate = startpoint.GetRelationship(*stop); + + if (relate == cFCOName::REL_ABOVE) + { + pStopPtSet->Add( *stop ); + } + } + + pStopPtSet->SetRecurseDepth( -1 == depth ? cFCOSpecStopPointSet::RECURSE_INFINITE : depth ); + pfcospec->SetHelper( pStopPtSet ); + } + // + ////////////////////////////////////////////////////////////// + + // + // set start point + // + pfcospec->SetStartPoint( startpoint ); + + // + // set default mask + // + const iFCOSpecMask *pdefspecmask = iFCOSpecMask::GetDefaultMask(); + ASSERT(pdefspecmask != 0); + + // + // build property vector + // + cFCOPropVector v = (*rule)->GetDefSpecMask().GetPropVector(); + pHelper->AddSubTypeProps( v ); + pfcospec->SetPropVector( pdefspecmask, v); + + // + // add attributes + // + TSTRING strAttrVal; + cParseNamedAttrList* pal = (*rule)->GetAttrList(); + cFCOSpecAttr* pAttr = new cFCOSpecAttr; + if( pal != NULL ) + { + // TODO: make storage place for these keywords + // attribute names are stored in lowercase + const cParseNamedAttr* pa; + + // + // get rulename + // + pa = pal->Lookup( TSS_GetString( cTWParser, twparser::STR_PARSER_RULENAME ) ); + if( pa ) + { + // TODO -- at some future date, remove the name in the spec + // and only set it in pAttr + pfcospec->SetName( pa->GetValue() ); + pAttr->SetName( pa->GetValue() ); + } + + // + // get severity + // + pa = pal->Lookup( TSS_GetString( cTWParser, twparser::STR_PARSER_SEVERITY ) ); + if( pa ) + { + int iSev; + cSeverityLimits sl; + if( ! sl.InterpretInt( pa->GetValue(), &iSev ) ) + throw eParserBadSevVal( pa->GetValue(), pa->GetLineNum() ); + + pAttr->SetSeverity( iSev ); + } + + // + // get emailto + // + pa = pal->Lookup( TSS_GetString( cTWParser, twparser::STR_PARSER_EMAILTO ) ) ; + if( pa ) + { + TSTRING strAddressee; + int index = 0; + while( cParserUtil::GetNextMailName( pa->GetValue(), strAddressee, index++ ) ) + { + d.TraceDebug( _T("email to recip: <%s>\n"), strAddressee.c_str() ); + pAttr->AddEmail( strAddressee ); + } + } + } + + // + // store rule in the spec list + // + fcospeclist.Add( pfcospec, pAttr ); + pfcospec->Release(); + pAttr->Release(); + } + + delete pHelper; +} +/////////////////////////////////////////////////////////////////////////////// +// CreatePropVector -- given the string representation of the attribute vector, +// create an FCOPropVector +/////////////////////////////////////////////////////////////////////////////// +void cParserUtil::CreatePropVector( const TSTRING& strPropListC, class cFCOPropVector& v, iParserGenreUtil* pHelper ) +{ + ASSERT( pHelper != NULL ); + + // state: turning modes on or off + enum Mode { MO_TURNON, MO_TURNOFF }; + Mode mode = MO_TURNON; + + // clear out all spaces in the string + TSTRING strPropList = strPropListC; + util_EatAllSpaces( strPropList ); + + // zero it out + v.Clear(); + + TSTRING::const_iterator iter; + TSTRING::size_type i; // index into string + for ( iter = strPropList.begin(), i = 0; iter != strPropList.end(); iter++, i++ ) + { + int propIndex = -1; // index into propvector + + switch (*iter) + { + ///////////////////////////////////////////////////////////// + // parsing modes + case '+': + mode = MO_TURNON; + continue; + case '-': + mode = MO_TURNOFF; + continue; + ///////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////// + // long attribute names + case '&': + { + // + // collect string + // + + // find next '&', '+', or '-' + TSTRING::size_type next = util_FindNextDelim( strPropList, i+1 ); + + // get attribute name + TSTRING strProp; + if( next == TSTRING::npos ) + strProp = strPropList.substr( i+1 ); + else + strProp = strPropList.substr( i+1, next - i - 1 ); + + // increment past string + iter += strProp.length(); + i += strProp.length(); + + // map attribute + if( ! pHelper->MapStringToProperty( strProp, propIndex ) ) + throw eParserPropChar( strProp ); + } + break; + ///////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////// + // not '+' or '-' or '&' so map the char to a property + default: + if( ! pHelper->MapStringToProperty( TSTRING( 1, *iter ), propIndex ) ) + throw eParserPropChar( TSTRING( 1, *iter ) ); + break; + // + ///////////////////////////////////////////////////////////// + } + + // now turn on or turn off bit, according to mode + ASSERT( propIndex != -1 ); + if (mode == MO_TURNON) + v.AddItemAndGrow( propIndex ); + else + v.RemoveItem( propIndex ); + } + + /* for 1.5, allow no properties (just track file existence) + // if v is empty, error + cFCOPropVector emptyPropVector; + emptyPropVector.Clear(); + if( v == emptyPropVector ) + { + d.TraceError("CreatePropVector failed!!\n"); + throw eError( ERR_BAD_PROP_STRING, strPropV.c_str() ); + } + */ + + return; +} + +// gets semicolon-delimited words in a string. index starts at 0. +// strNameRet has surronding WS discarded +bool cParserUtil::GetNextMailName( const TSTRING& strNameList, TSTRING& strNameRet, int index ) +{ + ASSERT( index >= 0 ); + + // go to nth name + TSTRING::size_type nextSC, lastSC = (TSTRING::size_type)-1; // algorithm starts searching for next ';' + // at lastSC+1 + for( ; index >= 0; index-- ) + { + nextSC = strNameList.find( _T(';'), ( lastSC + 1 ) ); + + if( 0 == index ) // if the name # we're looking for + { + strNameRet = strNameList.substr( ( lastSC + 1 ), TSTRING::npos == nextSC ? TSTRING::npos : nextSC - ( lastSC + 1 ) ); + util_LoseSurroundingWS( strNameRet ); + return true; + } + else if( TSTRING::npos == nextSC ) // didn't get to index'th naem: no names left + { + return false; + } + + lastSC = nextSC; + } + + // unreachable code + ASSERT( false ); + return false; // just to placate the compiler +} + +void cParserUtil::MergeMailLists( TSTRING& tstrMergeIntoMe, const TSTRING& tstrRHS ) +{ + // foreach word in rhs + TSTRING tstrWordToAdd; + int index = 0; + while( cParserUtil::GetNextMailName( tstrRHS, tstrWordToAdd, index++ ) ) + { + // if it isn't in lhs, add it + bool fAlreadyInList = false; + int index2 = 0; + TSTRING tstrWordInLHS; + while( !fAlreadyInList && cParserUtil::GetNextMailName( tstrMergeIntoMe, tstrWordInLHS, index2++ ) ) + { + if( 0 == tstrWordInLHS.compare( tstrWordToAdd ) ) + fAlreadyInList = true; + } + + if( ! fAlreadyInList ) + { + tstrMergeIntoMe += _T(";"); + tstrMergeIntoMe += tstrWordToAdd; + } + } +} + + +bool cParserHelper::AtTopScope() +{ + return( mScopedAttrs.empty() ); +} + +void cParserHelper::PopScope() +{ + ASSERT( ! mScopedAttrs.empty() ); + + delete mScopedAttrs.back(); + mScopedAttrs.pop_back(); +} + +cParseNamedAttrList* cParserHelper::GetGlobalAttrList() +{ + if( ! mScopedAttrs.empty() ) + return mScopedAttrs.back()->GetAttrList(); + else + return NULL; +} + +void cParserHelper::IncrementScopeStatementCount() +{ + // must add count to ALL previous scopes. + for( ScopedAttrContainer::iterator i = mScopedAttrs.begin(); i != mScopedAttrs.end(); i++ ) + (*i)->IncrementStatementCount(); +} + +int cParserHelper::GetScopeStatementCount() +{ + if( ! mScopedAttrs.empty() ) + { + return mScopedAttrs.back()->GetStatementCount(); + } + else + { + // should never ask for this when we aren't in a scope + ASSERT( false ); + return 0; + } +} + + +void cParserHelper::PushScope( cAttrScopeInfo* pSI ) +{ + // add previous scope's info to this one + if( ! mScopedAttrs.empty() ) + { + pSI->GetAttrList()->MergeNoOverwrite( mScopedAttrs.back()->GetAttrList() ); + } + + mScopedAttrs.push_back( pSI ); +} + + +//========================================================================= +// UTIL FUNCTION CODE +//========================================================================= + +int util_ConvertHex(const char* const cpsz, int* const pnCharsRead) +{ + ASSERT( util_AsciiCharsActLikeTheyShould() ); + ASSERT( cpsz && pnCharsRead ); + + if (*cpsz == 0 || !std::isxdigit( *cpsz, std::locale() )) + throw eParserBadHex( cStringUtil::StrToTstr( cpsz ) ); + + int iValue; + const char* psz = cpsz; + for( + *pnCharsRead = 0, iValue = 0; + *psz && std::isxdigit( *psz, std::locale() ) && (*pnCharsRead < 2); + psz++, (*pnCharsRead)++ + ) + { + iValue *= 0x10; + + if( std::isdigit( *psz, std::locale() ) ) + { + iValue += ( *psz - '0' ); + } + else + { + if( std::islower( *psz, std::locale() ) ) + iValue += ( *psz - 'a' + 10 ); // so that A=10, B=11, ..., F=15 + else // is uppercase + iValue += ( *psz - 'A' + 10 ); // so that a=10, a=11, ..., f=15 + } + } + + return iValue; +} + +int util_ConvertUnicode(const char* const cpsz, int* const pnCharsRead) +{ + ASSERT( util_AsciiCharsActLikeTheyShould() ); + ASSERT( cpsz && pnCharsRead ); + + if (*cpsz == 0 || !std::isxdigit( *cpsz, std::locale() )) + throw eParserBadHex( cStringUtil::StrToTstr( cpsz ) ); + + int iValue; + const char* psz = cpsz; + for( + *pnCharsRead = 0, iValue = 0; + *pnCharsRead < 4; + psz++, (*pnCharsRead)++ + ) + { + // we require 4 chars for unicode escapes + if (*psz == 0 || !std::isxdigit( *psz, std::locale() )) + throw eParserBadHex( cStringUtil::StrToTstr( cpsz ) ); + + iValue *= 0x10; + + if( std::isdigit( *psz, std::locale() ) ) + { + iValue += ( *psz - '0' ); + } + else + { + if( std::islower( *psz, std::locale() ) ) + iValue += ( *psz - 'a' + 10 ); // so that A=10, B=11, ..., F=15 + else // is uppercase + iValue += ( *psz - 'A' + 10 ); // so that a=10, a=11, ..., f=15 + } + } + + return iValue; +} + +// only 3 octal chars allowed +int util_ConvertOctal( const char* psz, int* const pnCharsRead ) +{ + ASSERT( util_AsciiCharsActLikeTheyShould() ); + ASSERT( psz && pnCharsRead ); + ASSERT( util_IsOctal( *psz ) ); // at least one oct char + + int iValue; + for( + iValue = 0, *pnCharsRead = 0; + *psz && util_IsOctal( *psz ) && *pnCharsRead < 3; // limit of 3 octal chars + psz++, (*pnCharsRead)++ + ) + { + iValue *= 010; + iValue += ( *psz - '0' ); + } + + return( iValue ); +} + +bool util_IsOctal( const char ch ) +{ + ASSERT( util_AsciiCharsActLikeTheyShould() ); + + return( ch >= '0' && ch <= '7' ); +} + +int util_GetEscapeValueOfChar( char ch ) +{ + int iValue = -1; + + switch( ch ) + { + case 'n': + iValue = 10; + break; + case 't': + iValue = 9; + break; + case 'v': + iValue = 11; + break; + case 'b': + iValue = 8; + break; + case 'r': + iValue = 13; + break; + case 'f': + iValue = 12; + break; + case 'a': + iValue = 7; + break; + case '\\': + iValue = 92; + break; + case '\?': + iValue = 63; + break; + case '\'': + iValue = 39; + break; + case '\"': + iValue = 34; + break; + default: + { + // unrecognized escape char: just return character + iValue = static_cast( ch ); + } + break; + } + + ASSERT( iValue != -1 ); //should have *some* value at this point + + return( iValue ); +} + + +// -1 means recurse all levels +int util_GetRecurseDepth( const cParseNamedAttrList* pList ) //throw( eParserHelper ) +{ + if( pList != NULL ) + { + const cParseNamedAttr* pa = pList->Lookup( TSS_GetString( cTWParser, twparser::STR_PARSER_RECURSE ) ); + if( pa ) + { + TSTRING str = pa->GetValue(); + + std::transform( str.begin(), str.end(), str.begin(), _totlower ); + + if( 0 == str.compare( TSS_GetString( cTWParser, twparser::STR_PARSER_FALSE ) ) ) + { + return 0; + } + else if( 0 == str.compare( TSS_GetString( cTWParser, twparser::STR_PARSER_TRUE ) ) ) + { + return -1; + } + else + { + // must be number + int i; + cRecurseDepthLimits rdl; + if( ! rdl.InterpretInt( str, &i ) ) + throw eParserUnrecognizedAttrVal( str, pa->GetLineNum() ); + return i; + } + } + } + + return( -1 ); // defaults to recurse all levels +} + +// finds first '&', '+', '-' on or after str[i] +TSTRING::size_type util_FindNextDelim( const TSTRING& str, TSTRING::size_type i ) +{ + TSTRING::size_type min = TSTRING::npos; + TSTRING::size_type amp = str.find( '&', i ); + TSTRING::size_type plus = str.find( '+', i ); + TSTRING::size_type minus = str.find( '-', i ); + + // now find minimum of the three + if( amp != TSTRING::npos ) + min = amp; + if( min != TSTRING::npos && plus != TSTRING::npos && plus < min ) + min = plus; + if( min != TSTRING::npos && minus != TSTRING::npos && minus < min ) + min = minus; + + return min; +} + +// deletes each space in the string +void util_EatAllSpaces( TSTRING& str ) +{ + for( TSTRING::iterator i = str.begin(); i != str.end(); i++ ) + { + if( *i == _T(' ') ) + { + str.erase( i ); + } + } +} + +void util_LoseSurroundingWS( TSTRING& str ) +{ + TSTRING::size_type nonWSStart = str.find_first_not_of( _T(" \t"), 0 ); + TSTRING::size_type nonWSEnd = str.find_last_not_of( _T(" \t") ); + + if( TSTRING::npos == nonWSStart ) // if only whitespace + { + ASSERT( TSTRING::npos == nonWSEnd ); + str = str.erase(); + } + else // has non WS chars + { + ASSERT( TSTRING::npos != nonWSEnd ); + str = str.substr( nonWSStart, nonWSEnd - nonWSStart + 1 ); + } +} + + +#ifdef _DEBUG +bool util_AsciiCharsActLikeTheyShould() +{ + // we need numbers whose character + // representation increase by one + return( + ( '0' < '1' ) && + ( '0' + 1 == '1' ) && + ( 'a' < 'b' ) && + ( 'a' + 1 == 'b' ) && + ( 'A' < 'B' ) && + ( 'A' + 1 == 'B' ) + ); +} +#endif + diff --git a/src/twparser/parserhelper.h b/src/twparser/parserhelper.h new file mode 100644 index 0000000..e39e90a --- /dev/null +++ b/src/twparser/parserhelper.h @@ -0,0 +1,271 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// parserhelper.h -- helper classes that are called by yacc parser +// + +#ifndef __PARSERHELPER_H +#define __PARSERHELPER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __PARSEROBJECT_H +#include "parserobjects.h" +#endif + +#ifndef __GENREPARSEINFO_H +#include "genreparseinfo.h" +#endif + +#ifndef __ERRORBUCKETIMPL_H +#include "core/errorbucketimpl.h" +#endif + +#ifndef __FCOGENRE_H +#include "fco/fcogenre.h" +#endif + +#ifndef __GENRESPECLIST_H +#include "fco/genrespeclist.h" +#endif + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class iParserGenreUtil; +class cGenrePolicy; +class cFCOPropVector; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//////////////////////////////////////////////////////////// +// Parser Base Exception +//////////////////////////////////////////////////////////// +TSS_BEGIN_EXCEPTION_NO_CTOR( eParserHelper, eError ) + enum { CURRENT_LINE = -1, NO_LINE = 0 }; + // if ( nLine != NO_LINE ) appends the "Line number: " to the + // end of the strMsg if fShowLineNum is true, then returns string + eParserHelper( const TSTRING& strMsg, int nLine = CURRENT_LINE ); +TSS_END_EXCEPTION(); + +//////////////////////////////////////////////////////////// +// Helper Macro For Parser Exceptions +//////////////////////////////////////////////////////////// +#define TSS_PARSER_EXCEPTION( except ) \ + TSS_BEGIN_EXCEPTION_NO_CTOR( except, eParserHelper ) \ + except( const TSTRING& strMsg, int nLine = CURRENT_LINE ) \ + : eParserHelper( strMsg, nLine ) \ + {}; \ + TSS_END_EXCEPTION() + +//////////////////////////////////////////////////////////// +// Parser Exceptions +//////////////////////////////////////////////////////////// +TSS_PARSER_EXCEPTION( eParseFailed ); +TSS_PARSER_EXCEPTION( eParserRedefineVar ); +TSS_PARSER_EXCEPTION( eParserUnrecognizedAttr ); +TSS_PARSER_EXCEPTION( eParserUnrecognizedAttrVal ); +TSS_PARSER_EXCEPTION( eParserPropChar ); +TSS_PARSER_EXCEPTION( eParserNoRules ); +TSS_PARSER_EXCEPTION( eParserNoRulesInSection ); +TSS_PARSER_EXCEPTION( eParserUseUndefVar ); +TSS_PARSER_EXCEPTION( eParserBadSevVal ); +TSS_PARSER_EXCEPTION( eParserBadFCONameFmt ); +TSS_PARSER_EXCEPTION( eParserSectionAlreadyDefined ); +TSS_PARSER_EXCEPTION( eParserPointAlreadyDefined ); +TSS_PARSER_EXCEPTION( eParserSectionInsideBlock ); +TSS_PARSER_EXCEPTION( eParserRelativePath ); +TSS_PARSER_EXCEPTION( eParserIgnoringSection ); +TSS_PARSER_EXCEPTION( eParserNoStatementsInScope ); +TSS_PARSER_EXCEPTION( eParserBadHex ); +TSS_PARSER_EXCEPTION( eParserBadCharacter ); + + +/////////////////////////////////////////////////////////////////////////////// +// class cPreprocessor +// used for directives #ifhost, to determine if parserhelper acts on input from parser +// if current state is STATE_ACCEPT, it will create specs from rules, set variables, etc. +// if current state is STATE_IGNORE, it will not. +// -- assumes there is at least one state in stack at all times +class cPreprocessor +{ +public: + cPreprocessor(); + + // + // if we're in accept, then we process + // input, otherwise we ignore it + // + enum AcceptState + { + STATE_ACCEPT, + STATE_IGNORE + }; + + // + // basic functionality + // + static void PushState( AcceptState state ); + static void PopState(); + static AcceptState TopState(); + static AcceptState GetState(); + static AcceptState UnderneathTopState(); // gets the item in the stack underneath top item + static AcceptState GetLastState() { return UnderneathTopState(); }; + static void ToggleTopState(); + static AcceptState GetOppositeState( AcceptState state ); + static bool AtTopLevel(); + static bool Empty() { return mStateStack.empty(); }; + // returns true if there is only one element in the stack + + static void IgnoreSection() { mfIgnoreSection = true; }; + static void ReadSection() { mfIgnoreSection = false; }; + +private: + // + // data members + // + typedef std::stack AcceptStack; + static AcceptStack mStateStack; + static bool mfIgnoreSection; +}; + +// encapsulates utility functions +class cParserUtil +{ +public: + // + // general utility functions + // + static void InterpretEscapedString( const std::string& strEscapedString, TSTRING& strInterpretedString ); + // converts escaped character sequences in strEscapedString into their escape characters in strInterpretedString + //( e.g. turns "Hello World!\n" (literal backslash) into "Hello World!" + // all C++ escape sequences are recognized: + // (1) octal numbers \012 (1, 2, or 3 octal digits), + // (2) hex numbers \x2AFB1... ( 'x' followed by one or more hex digits ), + // (3) chars: \t, \v, \b, \r, \f, \a, \\, \?, \', and \" + // (4) all other escaped chars are treated as if not escaped + static bool AnyOfTheseHostsExists( cParseStringList* pList ); + // is this machine is in pList? + + static bool GetNextMailName( const TSTRING& strNameList, TSTRING& strNameRet, int index ); + // gets semicolon-delimited words in a string. index starts at 0. + static void MergeMailLists( TSTRING& tstrMergeIntoMe, const TSTRING& tstrRHS ); + // merges semicolon-delimited mailnames. will not add a duplicate name. + + static void CreatePropVector( const TSTRING& attr, cFCOPropVector& v, iParserGenreUtil* pHelper ); // throw( eParserHelper ) + // takes a string of the form (+pinguam...) and turns it into a file system property vector; throws an error if + // the string is in an invalid format. Grows the prop vector if necessary. + static void CreateFCOSpecs( cGenre::Genre g, cGenreParseInfo* pgpi, cFCOSpecList &fcospeclist ); // throw( eParserHelper ) + // this uses the internal list of rules and stop points to generate the list of + // fco specs. +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// this class exists only to encapsulate the routines to help the parser +// along -- the goal is to reduce the code that lives in the yacc +// +class cParserHelper +{ +public: + static void Init( cErrorBucket* pE ); // initializes static member vars + static void Finit( cGenreSpecListVector* pPolicy ); // creates policy and cleans up + + // + // data accesss + // + static cErrorBucket* GetErrorBucket() { ASSERT( mpError != 0 ); return mpError; }; + static int GetLineNumber() { return miLineNum; }; + static void IncrementLineNumber() { ++miLineNum; }; + + // + // specify whether to parse entire file for correctness checking + // + static void SetParseOnly( bool f ) { mfParseOnly = f; }; + static bool ParseOnly() { return mfParseOnly; }; + + // + // genre info + // + static cGenreParseInfo* GetGenreInfo(); + static void SetSection( TSTRING& strSection ); // throw( eParserHelper ) + + // + // scoped attribute info + // + static void PushScope( cAttrScopeInfo* pSI ); + static void PopScope(); + static bool AtTopScope(); + static cParseNamedAttrList* GetGlobalAttrList(); + static void IncrementScopeStatementCount(); + static int GetScopeStatementCount(); + static bool ScopeEmpty() { return mScopedAttrs.empty(); }; + + + static bool InsertGlobalVariable( const TSTRING& var, const TSTRING& val); //throw( eParserHelper ) + // Insert a variable into mGlobalVarTable. + + static cSymbolTable& GetGlobalVarTable( void ) { return mGlobalVarTable; } + // Returns a reference to mGlobalVarTable. +private: + + static void CleanUp(); // frees memory + + static cSymbolTable mGlobalVarTable; + // A table for all the global variable definitions. + // + // data members + // + static cErrorBucket* mpError; + // holds errors that the parser creates + static int miLineNum; + // current line number (set in lexer) + typedef std::map< cGenre::Genre, cGenreParseInfo* > GenreContainer; + static GenreContainer mAph; // holds only genres that have been defined + // genre helpers + typedef std::list ScopedAttrContainer; + static ScopedAttrContainer mScopedAttrs; + // scoped attributes + static cGenreParseInfo* pCurrentGenreInfo; + static const cGenre::Genre mDefaultGenre; // default genre for this OS + static const cGenre::Genre mAcceptedGenres[5]; // what genres we recognize for this OS. terminated with a -1 + static bool mfParseOnly; +}; + + +#endif + diff --git a/src/twparser/parserobjects.cpp b/src/twparser/parserobjects.cpp new file mode 100644 index 0000000..cdd82f2 --- /dev/null +++ b/src/twparser/parserobjects.cpp @@ -0,0 +1,397 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// parserobjects.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= +#include "stdtwparser.h" +#include "parserobjects.h" +#include "parserhelper.h" +#include "core/twlimits.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +// +// cParseRule +// + +cParseRule::~cParseRule() +{ + delete mpAttrList; + delete mpSpecMaskList; +} + +const cFCOName& cParseRule::GetName() const +{ + return mName; +} + +void cParseRule::SetName( const cFCOName& name ) +{ + mName = name; +} + +cParseNamedAttrList * +cParseRule::GetAttrList() const +{ + return mpAttrList; +} + +void +cParseRule::SetAttrList(cParseNamedAttrList *pattr) +{ + mpAttrList = pattr; +} + +/////////////////////////////////////////////////////////////////////////////// +// SetSpecMaskList +// attaches cParseSpecMaskList to this structure +/////////////////////////////////////////////////////////////////////////////// +void +cParseRule::SetSpecMaskList(cParseSpecMaskList *pmasks) +{ + mpSpecMaskList = pmasks; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetNumSpecMasks +// returns number of specmasks in list (excluding default) +/////////////////////////////////////////////////////////////////////////////// +int +cParseRule::GetNumSpecMasks() const +{ + // empty list? + if (mpSpecMaskList == NULL) + return 0; + + return mpSpecMaskList->mList.size(); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetNumNamedAttrs +// returns number of named attributes in list +/////////////////////////////////////////////////////////////////////////////// +int +cParseRule::GetNumNamedAttrs() const +{ + // empty list? + if (mpAttrList == NULL) + return 0; + + return mpAttrList->mList.size(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Dump +// dumps out all the contents of the parse node, including children +/////////////////////////////////////////////////////////////////////////////// + +void +cParseRule::Dump() +{ + cDebug d("\tcParseRule::Dump()"); + + d.TraceDebug("name=%s\n", mName.AsString().c_str()); + d.TraceDebug("defspecmask.prop_vector=%s\n", mDefSpecMask.GetPropVectorString().c_str() ); + d.TraceDebug("defspecmask.condition=%s\n", mDefSpecMask.GetCondition().c_str() ); + + // specmasks + d.TraceDebug(" numspecmasks=%d\n", GetNumSpecMasks()); + if( mpSpecMaskList ) + mpSpecMaskList->Dump(d); + + // named attributes + d.TraceDebug(" numattrs=%d\n", GetNumNamedAttrs()); + if( mpAttrList ) + mpAttrList->Dump(d); +} + +// +// cParseSpecMask +// + +// constructor +cParseSpecMask::cParseSpecMask(TSTRING &condition, TSTRING &attr, iParserGenreUtil* pHelper ) // throw( eParserHelper ) + : msCondition(condition), msPV( attr ), mPropVector(), mpAttrList(NULL) +{ + cParserUtil::CreatePropVector( msPV, mPropVector, pHelper ); +} + +cParseSpecMask::~cParseSpecMask() +{ + delete mpAttrList; +} + +int +cParseSpecMask::GetNumAttrs() const +{ + if (mpAttrList == NULL) + return 0; + + return mpAttrList->mList.size(); +} + +void +cParseSpecMask::SetAttrList(cParseNamedAttrList *pattr) +{ + mpAttrList = pattr; +} + +cParseNamedAttrList * +cParseSpecMask::GetAttrList() const +{ + return mpAttrList; +} + +const TSTRING& cParseSpecMask::GetPropVectorString() const +{ + return msPV; +} + +const cFCOPropVector& cParseSpecMask::GetPropVector() const +{ + return mPropVector; +} + +const TSTRING& cParseSpecMask::GetCondition() const +{ + return msCondition; +} + +void +cParseSpecMask::Dump(cDebug &d) const +{ + d.TraceDebug(" condition=(%s), propvector=:\n", msCondition.c_str(), msPV.c_str() ); + + // dump list of attributes + if (mpAttrList) + mpAttrList->Dump(d); +} + +// +// cParseSpecMaskList +// + +void +cParseSpecMaskList::Dump(cDebug &d) const +{ + std::list::const_iterator ispec; + for (ispec = mList.begin(); ispec != mList.end(); ispec++) { + (*ispec)->Dump(d); + } +} + +// +// cParseNamedAttr +// + +// constructor +cParseNamedAttr::cParseNamedAttr( const TSTRING& name, const TSTRING& value ) + : mstrName(name), mstrValue(value), mLineNum( cParserHelper::GetLineNumber() ) +{ + // convert name to lowercase + std::transform( mstrName.begin(), mstrName.end(), mstrName.begin(), _totlower ); +} + +cParseNamedAttr* cParseNamedAttr::Clone() const +{ + cParseNamedAttr* pNew = new cParseNamedAttr( mstrName, mstrValue ); + pNew->mLineNum = mLineNum; + return pNew; +} + +void cParseNamedAttr::Dump(cDebug &d) const +{ + d.TraceDebug(" name=(%s), value=(%s)\n", mstrName.c_str(), mstrValue.c_str()); +} + +void cParseNamedAttr::Validate() const +{ + if( NamesMatch( twparser::STR_PARSER_RULENAME, mstrName ) ) + { + // no checking needed + } + else if( NamesMatch( twparser::STR_PARSER_EMAILTO, mstrName ) ) + { + // no checking needed + } + else if( NamesMatch( twparser::STR_PARSER_SEVERITY, mstrName ) ) + { + int iIgnore; + cSeverityLimits sl; + if( ! sl.InterpretInt( mstrValue, &iIgnore ) ) + throw eParserBadSevVal( mstrValue, mLineNum ); + } + else if( NamesMatch( twparser::STR_PARSER_RECURSE, mstrName ) ) + { + TSTRING str = mstrValue; + std::transform( str.begin(), str.end(), str.begin(), _totlower ); + + if( !NamesMatch( twparser::STR_PARSER_FALSE, str ) && !NamesMatch( twparser::STR_PARSER_TRUE, str ) ) + { + // must be number + int iIgnore; + cRecurseDepthLimits rdl; + if( ! rdl.InterpretInt( str, &iIgnore ) ) + throw eParserUnrecognizedAttrVal( mstrValue, mLineNum ); + } + } + else + { + throw eParserUnrecognizedAttr( mstrName, mLineNum ); + } +} + +// case sensitive-matching +bool cParseNamedAttr::NamesMatch( int nString, const TSTRING& strName ) const +{ + return ( 0 == strName.compare( TSS_GetString( cTWParser, nString ) ) ); +} + +// +// cParseNamedAttrList +// + + +cParseNamedAttrList::~cParseNamedAttrList() +{ + Clear(); +} + +void cParseNamedAttrList::Clear() +{ + for( std::list::iterator iter = mList.begin(); iter != mList.end(); iter++ ) + { + delete *iter; + } + mList.clear(); +} + +void +cParseNamedAttrList::Dump(cDebug &d) const +{ + // dump out each named attribute + std::list::const_iterator iattr; + for (iattr = mList.begin(); iattr != mList.end(); iattr++) { + (*iattr)->Dump(d); + } +} + + +void cParseNamedAttrList::Add( cParseNamedAttr* const pa ) +{ + ASSERT( pa != 0 ); + + pa->Validate(); + + // if not already in list, just put it in + constListIter iter = Find( pa ); + if( iter == mList.end() ) + { + mList.push_back( pa ); + } + else // set value of pa already in list + { + (*iter)->SetValue( pa->GetValue() ); + } +} + + +cParseNamedAttrList::constListIter cParseNamedAttrList::Find( const cParseNamedAttr* const pa ) +{ + ASSERT( pa != 0 ); + + for( + std::list< cParseNamedAttr * >::const_iterator iter = mList.begin(); + iter != mList.end(); + iter++ + ) + { + if( (*iter)->GetName() == pa->GetName() ) + { + return iter; + } + } + + return mList.end(); +} + +void cParseNamedAttrList::MergeNoOverwrite( const cParseNamedAttrList* const pal ) +{ + if( pal ) + { + // foreach attribute in pal + for( constListIter newIter = pal->mList.begin(); newIter != pal->mList.end(); newIter++ ) + { + // look for this attribute in this list + constListIter thisIter = Find( *newIter ); + + // if not already in list, just put it in + if( thisIter == mList.end() ) + { + mList.push_back( (*newIter)->Clone() ); + } + else // do not overwrite value (except for emailto) + { + // special case for emailto: this can have multiple values, so add the new value to the old value + if( 0 == (*thisIter)->GetName().compare( TSS_GetString( cTWParser, twparser::STR_PARSER_EMAILTO ) ) ) + { + TSTRING tstr = (*thisIter)->GetValue(); + cParserUtil::MergeMailLists( tstr, (*newIter)->GetValue() ); + (*thisIter)->SetValue( tstr ); + } + } + } + } +} + +const cParseNamedAttr* cParseNamedAttrList::Lookup( const TSTRING& tstrAttrName ) const +{ + constListIter i; + + for( i = mList.begin(); i != mList.end(); i++) + { + if( 0 == tstrAttrName.compare( (*i)->GetName() ) ) + { + return( *i ); + } + } + + return( NULL ); +} + diff --git a/src/twparser/parserobjects.h b/src/twparser/parserobjects.h new file mode 100644 index 0000000..c38bf7b --- /dev/null +++ b/src/twparser/parserobjects.h @@ -0,0 +1,309 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// parserobjects.h +// + +#ifndef __PARSEROBJECTS_H +#define __PARSEROBJECTS_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "twparserstrings.h" + +#ifndef __FCONAME_H +#include "fco/fconame.h" +#endif + +#ifndef __FCOPROPVECTOR_H +#include "fco/fcopropvector.h" +#endif + +//========================================================================= +// FORWARD DECLARATIONS +//========================================================================= + +class iParserGenreUtil; + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + +#define KILL_LIST(type, name) do { for( std::list::iterator iter = mList.begin(); iter != mList.end(); iter++ ) { delete *iter; } } while(0) + + +/////////////////////////////////////////////////////////////////////////////// +// parser representation of named attributes +// these {name, value} pairs can be associated with either rules, or rule masks. +// the implication is that each rule masks inherits the attributes of its parents, +// but can override them. +// +// Has knowledge of allowable attribute names and their allowable values +// Validate() throws error if name is unrecognized or value is outside allowable range +// + +class cParseNamedAttr +{ +public: + // + // ctors and dtors + // + cParseNamedAttr( const TSTRING& strName, const TSTRING& strValue ); // converts strName to lower before storing + cParseNamedAttr* Clone() const; + + const TSTRING& GetName() const { return mstrName; }; + const TSTRING& GetValue() const { return mstrValue; }; + int GetLineNum() const { return mLineNum; }; + void SetValue( const TSTRING& str ) { mstrValue = str; }; + + void Validate() const; + + // + // debug functions + // + void Dump(cDebug &d) const; // debugging routine + +private: + // + // dont' let C++ create these + // + cParseNamedAttr( const cParseNamedAttr& rhs ); + cParseNamedAttr& operator=( const cParseNamedAttr& rhs ); + + // + // enums + // + enum ValidAttrNames + { + NAME_1 = twparser::STR_PARSER_RULENAME, + NAME_2 = twparser::STR_PARSER_EMAILTO, + NAME_3 = twparser::STR_PARSER_RECURSE, + NAME_4 = twparser::STR_PARSER_SEVERITY, + MIN_NAME = NAME_1, + MAX_NAME = NAME_4 + }; + + bool NamesMatch( int nString, const TSTRING& strName ) const; + + // + // data members + // + TSTRING mstrName; + TSTRING mstrValue; + int mLineNum; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// wrapper around list routines +class cParseNamedAttrList +{ +public: + // + // ctors and dtors + // + cParseNamedAttrList() {}; + ~cParseNamedAttrList(); + + // + // typedefed iters + // + typedef std::list< cParseNamedAttr * >::const_iterator constListIter; + typedef std::list< cParseNamedAttr * >::const_reverse_iterator constListRevIter; + + // + // general functionality + // + void Dump( cDebug &d ) const; // dump entire list + void Add( cParseNamedAttr* const pa ); + const cParseNamedAttr* Lookup( const TSTRING& tstrAttrName ) const; + void Clear(); + void MergeNoOverwrite( const cParseNamedAttrList* const pal ); +private: + // + // private utils + // + constListIter Find( const cParseNamedAttr* const pa ); + + // + // dont' let C++ create these + // + cParseNamedAttrList( const cParseNamedAttrList& rhs ); + cParseNamedAttrList& operator=( const cParseNamedAttrList& rhs ); + + +public: + // + // data members + // + std::list< cParseNamedAttr * > mList; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// parser representation of fcospecmasks +// specmasks consist of sets of {condition, propvector} pairs, and also have associated +// with them a list of {attributes}. +class cParseSpecMask +{ +public: + // + // ctor and dtor + // + cParseSpecMask( TSTRING &condition, TSTRING &vector, iParserGenreUtil* pHelper ); // throw( eParserHelper ) + cParseSpecMask( const cParseSpecMask& sm ) { *this = sm; }; + ~cParseSpecMask(); + + // + // data access + // + void SetAttrList(cParseNamedAttrList *); // attach list of named attributes + cParseNamedAttrList *GetAttrList() const; + int GetNumAttrs() const; // number of named attributes + const cFCOPropVector& GetPropVector() const; // get prop vector (only used when parsing default specmasks) + const TSTRING& GetPropVectorString() const; + const TSTRING& GetCondition() const; // get condition + + // + // debug functionality + // + void Dump(cDebug &d) const; // debugging routine + +private: + // + // data members + // + TSTRING msCondition; // TODO: this shouldn't be a string -- should be expression + TSTRING msPV; + cFCOPropVector mPropVector; + cParseNamedAttrList* mpAttrList; // list of named attributes associated with specmask + +}; + +/////////////////////////////////////////////////////////////////////////////// +// wrapper around list routines +// we do this so yacc can have something convenient to carry around +class cParseSpecMaskList +{ +public: + ~cParseSpecMaskList() { KILL_LIST(cParseSpecMask,mList); }; + + void Dump(cDebug &d) const; // dump entire list + void Add( cParseSpecMask* const pa ) { mList.push_back( pa );}; + + std::list< cParseSpecMask* > mList; +}; + + +// parser representation of fcospecs, which is composed of... +// a rule name, a set of specmasks, a default specmask (required), and a set of named attributes +class cParseRule +{ +public: + // + // ctors and dtor + // + cParseRule( const cParseSpecMask& defSpecMask ) :mDefSpecMask( defSpecMask ), mpAttrList(0), mpSpecMaskList(0), mName(_T("")) {} + ~cParseRule(); + + // + // data access + // + const cFCOName& GetName() const; // rule name + void SetName( const cFCOName& name ); + cParseNamedAttrList*GetAttrList() const; // rule attributes + void SetAttrList(cParseNamedAttrList* ); + void SetSpecMaskList(cParseSpecMaskList *pmask); + // attach a list of specifiers to this rule (excluding default spec) + int GetNumSpecMasks() const; + // returns number of spec masks (excluding default rule) + int GetNumNamedAttrs() const; + // returns number of named attributes + const cParseSpecMask& GetDefSpecMask() const { return mDefSpecMask; }; + + // + // debugging functions + // + void Dump(); + +private: + // + // debugging functions + // + cParseSpecMask mDefSpecMask; // default specifier + cParseNamedAttrList* mpAttrList; // list of named attributes + cParseSpecMaskList* mpSpecMaskList; // list of specifiers + cFCOName mName; // name of fcospec +}; + + +/////////////////////////////////////////////////////////////////////////////// +// wrapper around TSTRING so yacc can have it inside the yylval union +// +class cParseString : public TSTRING +{ +public: + TSTRING& operator=( const TSTRING& str ) { return TSTRING::operator=( str ); }; +}; + + +class cParseStringList : public std::list< TSTRING > +{ +private: + std::list< TSTRING >& operator=( const std::list< TSTRING >& str ); +}; + + +// this class holds all info needed for an attribute scope +class cAttrScopeInfo +{ +public: + cAttrScopeInfo() :pAttrList(0), nStatements(0) {}; + + cParseNamedAttrList* GetAttrList() { return pAttrList; }; + void SetAttributes( cParseNamedAttrList* pL ) { pAttrList = pL; }; + void IncrementStatementCount() { nStatements++; }; + int GetStatementCount() { return nStatements; }; + +private: + cParseNamedAttrList* pAttrList; + int nStatements; +}; + +#endif //__PARSEROBJECTS_H + diff --git a/src/twparser/policyparser.cpp b/src/twparser/policyparser.cpp new file mode 100644 index 0000000..e8ec88d --- /dev/null +++ b/src/twparser/policyparser.cpp @@ -0,0 +1,269 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// policyparser.cpp -- intended to be used as interface to parser +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdtwparser.h" +#include "policyparser.h" +#include "core/twlocale.h" +#include "core/stringutil.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include +#ifdef HAVE_WCHAR_H +# include +#endif + +#include "core/ntmbs.h" + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +static std::string util_ConvertMB( const std::string& sIn ); +static bool util_ReadMBCharAsSBString( std::stringstream& ss, std::string& strCh ); +static std::string convert_to_encoded_hex( char ch ); +static std::string util_Output512Chars( const std::string& s ); + // don't want to pass debug a string over 1024, so play it safe with 512 + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + +// +// constructor +// +cPolicyParser::cPolicyParser( std::istream& in ) + : mParser(), mIn( in ) +{ +} + +void tw_yy_scan::output( int c ) +{ + TOSTRINGSTREAM sstr; + TCHAR sz[2]; + + sstr << TSS_GetString( cTWParser, twparser::STR_PARSER_INVALID_CHAR ); + + sz[0] = (unsigned char)c; // don't want to sign extend this + sz[1] = 0; + sstr << sz; + + throw eParseFailed( sstr.str() ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Check -- only checks syntax and basic semantics. +// +// on failure, it will throw an error +/////////////////////////////////////////////////////////////////////////////// +void cPolicyParser::Check( cErrorBucket* pError ) //throw(eError); +{ + cParserHelper::Init( pError ); + cParserHelper::SetParseOnly( true ); + + std::basic_stringstream in( ConvertMultibyte( mIn ) ); + tw_yy_scan lexer( in ); + + // start the parsing + if ( mParser.yyparse( &lexer ) != 0 ) + throw eParseFailed( _T("") ); + + cParserHelper::Finit( NULL ); +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute -- attempts to parse input to create list of fcospecs +// +// on failure, it will throw an error (binding failed, or parse error) +// on success, the list will be populated +/////////////////////////////////////////////////////////////////////////////// +void cPolicyParser::Execute( cGenreSpecListVector& policy, cErrorBucket* pError ) //throw( eParserHelper ) +{ + cParserHelper::Init( pError ); + + std::basic_stringstream in( ConvertMultibyte( mIn ) ); + tw_yy_scan lexer( in ); + + // start the parsing + if ( mParser.yyparse( &lexer ) != 0 ) + throw eParseFailed( _T("") ); + + cParserHelper::Finit( &policy ); +} + + +// NOTE: this version ALWAYS IGNORES the va_list!! Even though it says "...", +// it doesn't look at any args following pszErr +// Only call this with fully formatted message +// Parser will ALWAYS call the narrow-char version, so special case Unicode compile +void tw_yy_scan::yyerror( char* pszErr, ... ) //throw( eParserHelper ) +{ + TOSTRINGSTREAM ssError; // final error string + +#ifdef _UNICODE + // passed in strings are narrow so we need to convert them to wide + wchar_t szErrorW[1024]; + size_t nWrote = ::mbstowcs( szErrorW, pszErr, strlen( pszErr ) + 1 ); + if ( nWrote == (size_t)-1 ) + throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); + ssError << szErrorW; +#else + ssError << pszErr; +#endif + + throw eParseFailed( ssError.str() ); +} + +// Throw this in the display encoder? +std::string cPolicyParser::ConvertMultibyte( std::istream& in ) +{ + // get this file as a stringstream + std::stringstream ss; + + while( true ) + { + // get next character + char ch; + in.get( ch ); + + // check stream state + if( in.eof() ) + break; // we're done! + if( in.bad() || in.fail() ) + throw eParserBadCharacter(); + + // add next character to output buffer + ss.put( ch ); + + // check stream state + if( ss.bad() || ss.fail() ) + throw eParserBadCharacter(); + } + +#ifdef _DEBUG + TCERR << _T("*** begin policy text ***") << std::endl; + std::cerr << ss.str() << std::endl; + TCERR << _T("*** end policy text ***") << std::endl << std::endl; +#endif + + // convert it to single byte escaped + std::string str = util_ConvertMB( ss.str() ); + +#ifdef _DEBUG + TCERR << _T("*** begin policy converted to ***") << std::endl; + std::cerr << str << std::endl; + TCERR << _T("*** end policy converted to ***") << std::endl << std::endl; +#endif + + return str; +} + +std::string convert_to_encoded_hex( char ch ) +{ + std::basic_stringstream< char > sstr; + + // set up stringstream + sstr.imbue( std::locale::classic() ); + sstr.setf( std::ios_base::hex, std::ios_base::basefield ); + + // get the num_put facet + const std::num_put< char > *pnp = 0, &np = tss::GetFacet( sstr.getloc(), pnp ); + + // output the char + sstr << "\\x"; + np.put( sstr, sstr, sstr.fill(), (long)(unsigned char)ch ); + + return sstr.str(); +} + +std::string util_ConvertMB( const std::string& sIn ) +{ + cDebug d( "cPolicyParser::util_ConvertMB" ); + + std::string sOut; + std::string::const_iterator at; + + for( at = sIn.begin(); + at != sIn.end(); + // at gets incremented when used.... + ) + { + int nBytes = ::mblen( (char*)&at[0], MB_CUR_MAX ); + if ( nBytes == -1 ) + { + d.TraceDebug( "Unrecognized Character: %c\n", *at ); + if ( (unsigned char)*at > 0x7F ) + { + d.TraceDebug( "Normalizing.\n" ); + sOut += convert_to_encoded_hex( *(at++) ); + } + else + { + d.TraceDebug( "Incorrectly Formed, Cannot Normalize!\n" ); + std::string s( 1, *at ); + TSTRING ts = cStringUtil::StrToTstr( s ); + throw eParserBadCharacter( ts ); + } + } + else if( nBytes == 0 ) + { + break; // done with sIn + } + else if( nBytes == 1 ) + { + sOut += *(at++); // regular SB char + } + else // ( nBytes > 1 ) + { + // mb char -- output it as encoded bytes + while( nBytes-- > 0 ) + { + ASSERT( at != sIn.end() ); + sOut += convert_to_encoded_hex( *(at++) ); + } + } + } + + return sOut; +} + diff --git a/src/twparser/policyparser.h b/src/twparser/policyparser.h new file mode 100644 index 0000000..50aa9a2 --- /dev/null +++ b/src/twparser/policyparser.h @@ -0,0 +1,145 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// policyparser.h -- wrapper around yacc generated classes. intended to be used +// as interface to parser +// +// cPolicyParser: object responsible for reading policy file, and +// generating list of FCOSpecs +// + +#ifndef __POLICYPARSER_H +#define __POLICYPARSER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TYPES_H +#include "types.h" +#endif + +#ifndef __PARSERHELPER_H +#include "parserhelper.h" +#endif + +#ifndef __GENREPARSEINFO_H +#include "genreparseinfo.h" +#endif + +#ifndef __GENRESPECLIST_H +#include "fco/genrespeclist.h" +#endif + +#ifndef YYNEWLINE +# include "twparser/yylex.h" +# include "twparser/yyparse.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +/////////////////////////////////////////////// +// wrapper around yy_scan +// we do this so we can overload member functions +class tw_yy_scan : public yy_scan +{ + enum { MAX_TOKEN_LENGTH = 1024 }; +public: + tw_yy_scan( std::istream& i ) : yy_scan( MAX_TOKEN_LENGTH ), mIn(i) {}; // need to increase token length over mks default + + virtual int yygetc() { return mIn.get(); }; + + virtual void yyerror( char *pszErr, ... ); //throw( eParserHelper ) + // this is the MKS error function. But, since some operating systems (e.g. like AIX) + // don't offer a vnsprintf, so there's no way we can safely output the error + // from the va_arg list to a string without possible buffer overflow. + // So, only call this function with a fully formatted message. + // NOTE: I repeat: this version ALWAYS IGNORES the va_list!! Even though it says "...", + + virtual void output(int c); //throw( eParserHelper ) + // this is what lex calls when it gets to a char that it doesn't recognize. + // we throw an error. +private: + tw_yy_scan( const tw_yy_scan& ); + tw_yy_scan& operator=( const tw_yy_scan& ); + + // input stream + std::istream& mIn; +}; + +/////////////////////////////////////////////// +// wrapper around yy_parse +// we do this so we can overload member functions +class tw_yy_parse : public yy_parse +{ + enum { PARSER_STATE_STACK_SIZE = 150 }; +public: + tw_yy_parse() : yy_parse( PARSER_STATE_STACK_SIZE ){}; // need to increase token length over mks default +private: + tw_yy_parse( const tw_yy_parse& ); + tw_yy_parse& operator=( const tw_yy_parse& ); +}; + +/////////////////////////////////////////////////////////////////////////////// +// cPolicyParser +// input: istream& -- parser input +// output: list of (iFCOSpec *) -- caller is responsible for freeing +// +// when parsing is done, this object can be destroyed, and no trace of the +// parsing should exist +// + +class cPolicyParser +{ +public: + cPolicyParser( std::istream& in ); // input source + + void Execute( cGenreSpecListVector& policy, cErrorBucket* pError ); //throw(eError); + void Check( cErrorBucket* pError ); //throw(eError); + // do the parsing +private: + cPolicyParser( const cPolicyParser& ); + cPolicyParser& operator=( const cPolicyParser& ); + + std::string ConvertMultibyte( std::istream& in ); + // turns all mb chars > 1 byte or unrecognizable chars + // into escaped hex (\xXX) + + tw_yy_parse mParser; + std::istream& mIn; +}; + + +#endif + diff --git a/src/twparser/policyparser_t.cpp b/src/twparser/policyparser_t.cpp new file mode 100644 index 0000000..458e03c --- /dev/null +++ b/src/twparser/policyparser_t.cpp @@ -0,0 +1,95 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// policyparser_t -- test policy files +// TODO: +// we should put lots of files in ./testfiles, and verify: +// 1. correct files parse correctly +// 2. incorrect files cause errors +// 3. slightly incorrect files cause errors + +#include "stdtwparser.h" +#include "core/debug.h" +#include "fco/fcospecimpl.h" +#include "parserhelper.h" +#include "policyparser.h" +#include "fs/fspropset.h" +#include "fco/fcospeclist.h" +#include "test/test.h" +#include + +// helper class that checks output of each fcospec +class cPolicyParserTester { +public: + static bool VerifyNameAndStartPoint(iFCOSpec *pfsspec, TSTRING &name); +}; + +void TestPolicyParser() +{ + cDebug d("TestPolicyParser()"); + + // + // file: pol.txt + // + try + { + cDebug::AddOutTarget(cDebug::OUT_STDOUT); + + std::ifstream in; + in.open( "../twparser/testfiles/pol.txt" ); + if( ! in.good() ) + throw eParserHelper( _T("couldn't open test file") ); + + cPolicyParser parser( in ); + + cGenreSpecListVector policy; + cErrorQueue errorQ; + cErrorReporter errorR; + cErrorTracer errorT; + + // set up an error bucket that will spit things to stderr + errorT.SetChild( &errorR ); + errorQ.SetChild( &errorT ); + + parser.Execute( policy, &errorQ ); + + return; + } + catch(eError& e) + { + TCERR << (int)e.GetID() << " : " << e.GetMsg().c_str() << std::endl; + return; + } + + return; +} + + diff --git a/src/twparser/stdtwparser.cpp b/src/twparser/stdtwparser.cpp new file mode 100644 index 0000000..bb8b146 --- /dev/null +++ b/src/twparser/stdtwparser.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtwparser.cpp +// Date....: 5/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwparser.h" + +// eof: stdtwparser.cpp diff --git a/src/twparser/stdtwparser.h b/src/twparser/stdtwparser.h new file mode 100644 index 0000000..43d8038 --- /dev/null +++ b/src/twparser/stdtwparser.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtwparser.h +// +// Standard includes for the parser project. +// + +#include "core/stdcore.h" + diff --git a/src/twparser/twparser.cpp b/src/twparser/twparser.cpp new file mode 100644 index 0000000..f67ab83 --- /dev/null +++ b/src/twparser/twparser.cpp @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// parser.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdtwparser.h" +#include "twparsererrors.h" +#include "twparser.h" + +//========================================================================= +// PUBLIC METHOD CODE +//========================================================================= + +TSS_ImplementPackage( cTWParser ) + +cTWParser::cTWParser() +{ + // + // set up dependencies + // + // TODO:BAM -- TSS_Dependency( ??? ); + + TSS_REGISTER_PKG_ERRORS( twparser ) +} + diff --git a/src/twparser/twparser.h b/src/twparser/twparser.h new file mode 100644 index 0000000..cd51a37 --- /dev/null +++ b/src/twparser/twparser.h @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: parser.h +// Date....: 05/07/99 +// Creator.: Brian McFeely (bmcfeely) +// +// The Package class for the TSS fs library module. +// + +#ifndef __TWPARSER_H +#define __TWPARSER_H + +//--Requirements + +#include "core/package.h" // for: Packaging Abstraction + +//--Classes + +TSS_BeginPackage( cTWParser ) + + TSS_DECLARE_STRINGTABLE; + + public: + cTWParser(); + +TSS_EndPackage( cTWParser ) + +#endif //#ifndef __TWPARSER_H + diff --git a/src/twparser/twparsererrors.cpp b/src/twparser/twparsererrors.cpp new file mode 100644 index 0000000..d3abacc --- /dev/null +++ b/src/twparser/twparsererrors.cpp @@ -0,0 +1,70 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////// +// twparsererrors.cpp +// +// Registers all error strings in the parser package +// + +#include "stdtwparser.h" +#include "twparsererrors.h" + +#include "parserhelper.h" + +TSS_BEGIN_ERROR_REGISTRATION( twparser ) + +// +// Parser Helper +// + +TSS_REGISTER_ERROR( eParserHelper(), _T("Policy file parsing problem.") ); +TSS_REGISTER_ERROR( eParseFailed(), _T("Policy file parsing problem.") ); +TSS_REGISTER_ERROR( eParserRedefineVar(), _T("Read only variables cannot be assigned a value.") ); +TSS_REGISTER_ERROR( eParserUnrecognizedAttr(), _T("Unrecognized attribute name.") ); +TSS_REGISTER_ERROR( eParserUnrecognizedAttrVal(), _T("Unrecognized attribute value.") ); +TSS_REGISTER_ERROR( eParserPropChar(), _T("Unrecognized property mask in policy file.") ); +TSS_REGISTER_ERROR( eParserNoRules(), _T("No rules specified in policy file.") ); +TSS_REGISTER_ERROR( eParserNoRulesInSection(), _T("No rules specified in section.") ); +TSS_REGISTER_ERROR( eParserUseUndefVar(), _T("Undefined variable used.") ); +TSS_REGISTER_ERROR( eParserBadSevVal(), _T("Severity value outside of allowable limits.") ); +TSS_REGISTER_ERROR( eParserBadFCONameFmt(), _T("Bad objectname format.") ); +TSS_REGISTER_ERROR( eParserSectionAlreadyDefined(), _T("Section already declared.") ); +TSS_REGISTER_ERROR( eParserPointAlreadyDefined(), _T("Rule already defined as a start or stop point of another rule.") ); +TSS_REGISTER_ERROR( eParserSectionInsideBlock(), _T("Section declaration inside another block.") ); +TSS_REGISTER_ERROR( eParserRelativePath(), _T("Relative paths are not allowed in the policy file.") ); +TSS_REGISTER_ERROR( eParserIgnoringSection(), _T("Ignoring unknown section.") ); +TSS_REGISTER_ERROR( eParserNoStatementsInScope(), _T("Scoped attributes section has no statements.") ); +TSS_REGISTER_ERROR( eParserBadHex(), _T("Bad hex value in policy file.") ); +TSS_REGISTER_ERROR( eParserBadCharacter(), _T("Bad character found in policy file.") ); + + +TSS_END_ERROR_REGISTRATION() diff --git a/src/twparser/twparsererrors.h b/src/twparser/twparsererrors.h new file mode 100644 index 0000000..04d2772 --- /dev/null +++ b/src/twparser/twparsererrors.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twparsererrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __PARSERERRORS_H +#define __PARSERERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( twparser ) + +#endif//__PARSERERRORS_H + diff --git a/src/twparser/twparserstrings.cpp b/src/twparser/twparserstrings.cpp new file mode 100644 index 0000000..5d6f81b --- /dev/null +++ b/src/twparser/twparserstrings.cpp @@ -0,0 +1,55 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twparserstrings.cpp +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwparser.h" +#include "twparser.h" +#include "twparserstrings.h" + +TSS_BeginStringtable( cTWParser ) + + TSS_StringEntry( twparser::STR_PARSER_INVALID_CHAR, _T("Invalid character: ") ), + TSS_StringEntry( twparser::STR_PARSER_RULENAME, _T("rulename") ), + TSS_StringEntry( twparser::STR_PARSER_EMAILTO, _T("emailto") ), + TSS_StringEntry( twparser::STR_PARSER_RECURSE, _T("recurse") ), + TSS_StringEntry( twparser::STR_PARSER_SEVERITY, _T("severity") ), + TSS_StringEntry( twparser::STR_PARSER_FALSE, _T("false") ), + TSS_StringEntry( twparser::STR_PARSER_TRUE, _T("true") ), + TSS_StringEntry( twparser::STR_PARSER_SECTION_GLOBAL, _T("GLOBAL") ), + TSS_StringEntry( twparser::STR_LINE_NUMBER, _T("Line number ") ), + TSS_StringEntry( twparser::STR_ERR2_PARSER_NO_RULES_IN_SECTION, _T("Section: ") ), + +TSS_EndStringtable( cTWParser ) diff --git a/src/twparser/twparserstrings.h b/src/twparser/twparserstrings.h new file mode 100644 index 0000000..57b02f2 --- /dev/null +++ b/src/twparser/twparserstrings.h @@ -0,0 +1,63 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twparserstrings.h +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#ifndef __TWPARSERSTRINGS_H +#define __TWPARSERSTRINGS_H + +#include "twparser.h" // for: STRINGTABLE syntax + +//--Message Keys + +TSS_BeginStringIds( twparser ) + + STR_PARSER_INVALID_CHAR, + STR_YYERROR_LINE_NUM_FMT, + STR_PARSER_RULENAME, + STR_PARSER_EMAILTO, + STR_PARSER_RECURSE, + STR_PARSER_SEVERITY, + STR_PARSER_FALSE, + STR_PARSER_TRUE, + STR_PARSER_SECTION_GLOBAL, + STR_LINE_NUMBER, + STR_ERR2_PARSER_NO_RULES_IN_SECTION + +TSS_EndStringIds( twparser ) + + +#endif//__PARSERSTRINGS_H + diff --git a/src/twparser/yylex.cpp b/src/twparser/yylex.cpp new file mode 100644 index 0000000..450c576 --- /dev/null +++ b/src/twparser/yylex.cpp @@ -0,0 +1,1239 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtwparser.h" + +#if defined(__OpenBSD__) /* OpenBSD's varargs seems wacky */ +# undef va_start +# ifdef __GNUC__ +# define va_start(ap, last) \ + ((ap) = (va_list)__builtin_next_arg(last)) +# else +# define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) +# endif +#endif /* __OpenBSD__ */ + +/* ..\. -a -o yylex.cpp -D yylex.h -P ..\..\mkslexyacc\etc\yylex.cpp -LC tokens.l */ +#define INITIAL 0 +#define globals 2 +const int yy_endst = 172; +const int yy_nxtmax = 2818; +#define YY_LA_SIZE 22 + +static unsigned int yy_la_act[] = { + 12, 37, 34, 37, 14, 37, 15, 37, 16, 37, 17, 37, 34, 37, 19, 37, + 20, 37, 21, 37, 22, 37, 23, 37, 24, 37, 25, 37, 34, 37, 37, 36, + 37, 35, 34, 26, 18, 14, 13, 12, 12, 37, 34, 37, 34, 34, 34, 34, + 34, 34, 34, 34, 32, 34, 34, 34, 34, 34, 34, 31, 34, 33, 34, 34, + 30, 34, 34, 29, 34, 34, 34, 34, 34, 28, 34, 34, 34, 34, 34, 34, + 27, 34, 34, 34, 34, 34, 34, 34, 0, 34, 34, 34, 34, 34, 0, 34, + 0, 0, 32, 31, 33, 30, 29, 28, 27, 12, 3, 11, 6, 11, 5, 11, + 6, 11, 11, 8, 11, 9, 11, 10, 11, 7, 6, 5, 4, 3, 3, 11, + 6, 11, 6, 6, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 1, + 6, 2, 1, 3, 0 +}; + +static unsigned char yy_look[] = { + 0 +}; + +static int yy_final[] = { + 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, + 30, 31, 32, 33, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, 42, + 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 59, + 61, 63, 64, 66, 67, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, + 82, 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 96, 96, 96, + 96, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, + 98, 99, 99, 99, 99, 99, 99, 100, 101, 101, 102, 102, 103, 103, 103, 103, + 103, 104, 104, 104, 104, 104, 104, 105, 106, 106, 106, 106, 108, 110, 112, 114, + 115, 117, 119, 120, 121, 121, 121, 122, 122, 123, 124, 125, 126, 126, 128, 130, + 131, 131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 145, 145, 145, + 145, 145, 145, 146, 146, 146, 146, 146, 146, 147, 148, 148, 148 +}; +#ifndef yy_state_t +#define yy_state_t unsigned char +#endif + +static yy_state_t yy_begin[] = { + 0, 29, 122, 140, 0 +}; + +static yy_state_t yy_next[] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 17, 15, 15, 1, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 1, 6, 16, 3, 14, 15, 15, 15, 10, 11, 15, 15, 12, 7, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 15, 8, 18, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4, 13, 5, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 24, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 21, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 25, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 27, 32, 23, 23, 38, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 39, 40, 41, 45, 28, 23, 23, 23, 28, 46, 23, 23, 47, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 28, 23, 48, 49, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 50, 51, 52, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 53, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 30, 33, 54, 55, 30, 33, 42, 56, 43, 57, 58, 59, 44, 60, 61, 62, + 63, 64, 67, 68, 69, 64, 70, 30, 33, 71, 72, 73, 74, 75, 76, 79, + 80, 64, 81, 82, 83, 64, 84, 85, 64, 86, 87, 88, 33, 93, 94, 95, + 33, 96, 100, 97, 101, 98, 102, 31, 64, 99, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 33, 112, 113, 114, 115, 116, 117, 118, 121, 119, 138, 139, 66, + 119, 143, 139, 141, 147, 148, 149, 141, 150, 151, 152, 153, 154, 36, 155, 78, + 156, 35, 159, 119, 160, 139, 161, 162, 37, 163, 141, 34, 164, 165, 166, 65, + 167, 168, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 77, + 172, 172, 172, 120, 172, 172, 172, 172, 91, 172, 142, 172, 90, 172, 172, 172, + 172, 172, 172, 92, 172, 172, 89, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 123, 130, 126, 126, 123, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 123, 131, 127, 125, 131, 126, 126, 126, 131, + 131, 126, 126, 131, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 128, 126, 129, 131, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 124, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 131, 131, 131, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 172, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 134, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 172, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 172, 172, 136, 136, 172, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 172, 172, 172, 172, 172, 136, 136, 136, 172, + 172, 136, 136, 172, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 172, 136, 172, 172, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 172, 172, 172, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 172, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 144, 144, 169, 172, 144, 144, 169, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 144, 144, + 169, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 170, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 146, 158, + 172, 145, 157, 0 +}; + +static yy_state_t yy_check[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 7, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 31, 15, 15, 37, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 38, 39, 40, 44, 1, 15, 15, 15, 1, 45, 15, 15, 46, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 15, 43, 48, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 49, 42, 51, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 35, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 29, 32, 53, 54, 29, 32, 36, 55, 36, 56, 34, 58, 36, 59, 60, 61, + 62, 63, 66, 67, 68, 63, 69, 29, 32, 70, 65, 72, 73, 74, 75, 78, + 79, 64, 80, 81, 82, 64, 77, 84, 63, 85, 86, 87, 33, 92, 93, 94, + 33, 95, 99, 91, 100, 91, 101, 29, 64, 91, 98, 103, 104, 97, 106, 90, + 108, 109, 110, 33, 111, 89, 113, 114, 115, 116, 117, 120, 30, 124, 123, 63, + 30, 142, 123, 140, 146, 147, 148, 140, 149, 145, 151, 152, 153, 32, 154, 64, + 155, 32, 158, 30, 159, 123, 160, 161, 32, 157, 140, 32, 163, 164, 165, 63, + 166, 167, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 64, + 255, 255, 255, 30, 255, 255, 255, 255, 33, 255, 140, 255, 33, 255, 255, 255, + 255, 255, 255, 33, 255, 255, 33, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 255, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 255, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 255, 255, 126, 126, 255, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 255, 255, 255, 255, 255, 126, 126, 126, 255, + 255, 126, 126, 255, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 255, 126, 255, 255, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 255, 255, 255, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 255, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 143, 144, 141, 255, 143, 144, 141, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 143, 144, + 141, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 141, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 143, 144, + 255, 143, 144, 0 +}; + +static yy_state_t yy_default[] = { + 172, 172, 15, 172, 172, 172, 172, 15, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 16, 172, 172, 16, 15, 172, 172, 3, 172, 1, 0, 172, 15, + 15, 172, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 172, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 64, 30, 172, 33, 172, 172, 126, 172, 172, 172, + 172, 172, 172, 172, 127, 172, 172, 127, 126, 125, 172, 123, 122, 172, 126, 126, + 172, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 141, 172, 144, 0 +}; + +static int yy_base[] = { + 0, 795, 767, 1024, 2819, 2819, 2819, 460, 2819, 2819, 2819, 2819, 2819, 142, 2819, 768, + 256, 2819, 2819, 2819, 512, 2819, 2819, 2819, 2819, 2819, 2819, 2819, 2819, 1271, 1347, 714, + 1272, 1315, 1189, 932, 1178, 667, 695, 691, 686, 2819, 777, 729, 689, 698, 698, 2819, + 725, 789, 2819, 792, 2819, 1178, 1172, 1172, 1173, 2819, 1192, 1177, 1189, 1184, 1186, 1288, + 1304, 1198, 1222, 1220, 1234, 1237, 1229, 2819, 1196, 1210, 1212, 1202, 2819, 1210, 1235, 1233, + 1248, 1250, 1240, 2819, 1208, 1223, 1225, 1215, 2819, 1248, 1241, 1223, 1211, 1221, 1217, 1213, + 2819, 1226, 1238, 1216, 1221, 1220, 2819, 1234, 1238, 2819, 1241, 2819, 1240, 1234, 1231, 1232, + 2819, 1251, 1235, 1247, 1242, 1244, 2819, 2819, 1291, 2819, 1431, 1349, 1347, 2455, 2199, 1687, + 2819, 2819, 2819, 2819, 2819, 1943, 2819, 2819, 2819, 2819, 2819, 2819, 1354, 2704, 1297, 2702, + 2703, 1268, 1250, 1260, 1256, 1252, 2819, 1271, 1255, 1267, 1263, 1266, 2819, 1284, 1264, 1275, + 1272, 1267, 2819, 1289, 1273, 1285, 1281, 1283, 2819, 2819, 1330, 2819, 2819 +}; + + +#line 152 "..\\..\\mkslexyacc\\etc\\yylex.cpp" + +// MKS LEX prototype scanner code +// Copyright 1991 by Mortice Kern Systems Inc. +// All rights reserved. + +// You can redefine YY_INTERACTIVE to be 0 to get a very slightly +// faster scanner: +#ifndef YY_INTERACTIVE +#define YY_INTERACTIVE 1 +#endif + +// You can compile with -DYY_DEBUG to get a print trace of the scanner +#ifdef YY_DEBUG +#undef YY_DEBUG +#define YY_DEBUG(fmt,a1,a2) fprintf(stderr,fmt,a1,a2) +#else +#define YY_DEBUG(fmt,a1,a2) +#endif + +const int MIN_NUM_STATES = 20; + +// Do *NOT* redefine the following: +#define BEGIN yy_start = +#define REJECT goto yy_reject +#define yymore() goto yy_more + +#line 10 "tokens.l" + +#include "stdtwparser.h" + +//#ifndef YYNEWLINE +# include "twparser/yylex.h" +# include "twparser/yyparse.h" +//#endif + +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#include + +#include "core/debug.h" + +#include "policyparser.h" +#include "parserhelper.h" +#include "genreparseinfo.h" +#include "core/stringutil.h" +#include "core/displayencoder.h" + + + +/* specify that the lexer exit on EOF */ +int yywrap() +{ + return 1; +} + +/* wrapper around cDebug tracing */ +void lextrace(const TCHAR*str) +{ + cDebug d("\t\t\t\tlexer"); + d.TraceDetail( _T("%s\n"), str); +} + +// since i've replaced this with a non-va_arg yyerror, +// call this when you hit a syntax error and then call +// the non-va_arg yyerror with the result +std::string FormatSyntaxError( char ch, const char* pszAdditionalMsg = NULL ) +{ + // TODO:BAM MKS will call yyerror with narrow-char hard-coded string, so if + // we do it here as well, I suppose that's OK. This should be eventually + // corrected. + + std::ostringstream ssErr; + ssErr << "Syntax error: \'" << ch << "\'"; + if( pszAdditionalMsg ) + ssErr << ", " << pszAdditionalMsg; + + return ssErr.str(); +} + +// saves typing +#define TRACE_RETURN(x) lextrace(_T(#x)); return x + +#line 178 "..\\..\\mkslexyacc\\etc\\yylex.cpp" + + +// Constructor for yy_scan. Set up tables +//#pragma argsused +yy_scan::yy_scan(int sz, char* buf, char* sv, yy_state_t* states) +{ + mustfree = 0; + if ((size = sz) < MIN_NUM_STATES + || (yytext = buf) == 0 + || (state = states) == 0) { + yyerror("Bad space for scanner!"); + exit(1); + } +#ifdef YY_PRESERVE + save = sv; +#endif +} +// Constructor for yy_scan. Set up tables +yy_scan::yy_scan(int sz) +{ + size = sz; + yytext = new char[sz+1]; // text buffer + state = new yy_state_t[sz+1]; // state buffer +#ifdef YY_PRESERVE + save = new char[sz]; // saved yytext[] + push = save + sz; +#endif + if (yytext == NULL +#ifdef YY_PRESERVE + || save == NULL +#endif + || state == NULL) { + yyerror("No space for scanner!"); + exit(1); + } + mustfree = 1; + yy_end = 0; + yy_start = 0; + yy_lastc = YYNEWLINE; + yyin = stdin; + yyout = stdout; + yylineno = 1; + yyleng = 0; +} + +// Descructor for yy_scan +yy_scan::~yy_scan() +{ + if (mustfree) { + mustfree = 0; + delete(yytext); + delete(state); +#ifdef YY_PRESERVE + delete(save); +#endif + } +} + +// Print error message, showing current line number +void +yy_scan::yyerror(char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); +#ifdef LEX_WINDOWS + // Windows has no concept of a standard error output! + // send output to yyout as a simple solution + if (yylineno) + fprintf(yyout, "%d: ", yylineno); + (void) vfprintf(yyout, fmt, va); + fputc('\n', yyout); +#else /* LEX_WINDOWS */ + if (yylineno) + fprintf(stderr, "%d: ", yylineno); + (void) vfprintf(stderr, fmt, va); + fputc('\n', stderr); +#endif /* LEX_WINDOWS */ + va_end(va); +} + + +#ifdef LEX_WINDOWS + +// The initial portion of the lex scanner +// In an windows environment, it will load the desired +// resources, obtain pointers to them, and then call +// the protected member win_yylex() to acutally begin the +// scanning. When complete, win_yylex() will return a +// value back to our new yylex() function, which will +// record that value temporarily, release the resources +// from global memory, and finally return the value +// back to the caller of yylex(). + +int +yy_scan::yylex() +{ + int wReturnValue; + HANDLE hRes_table; + unsigned short far *old_yy_la_act; // remember old pointer values + short far *old_yy_final; + yy_state_t far *old_yy_begin; + yy_state_t far *old_yy_next; + yy_state_t far *old_yy_check; + yy_state_t far *old_yy_default; + short far *old_yy_base; + + // the following code will load the required + // resources for a Windows based parser. + + hRes_table = LoadResource (hInst, + FindResource (hInst, "UD_RES_yyLEX", "yyLEXTBL")); + + // return an error code if any + // of the resources did not load + + if (hRes_table == (HANDLE)NULL) + return (0); + + // the following code will lock the resources + // into fixed memory locations for the scanner + // (remember previous pointer locations) + + old_yy_la_act = yy_la_act; + old_yy_final = yy_final; + old_yy_begin = yy_begin; + old_yy_next = yy_next; + old_yy_check = yy_check; + old_yy_default = yy_default; + old_yy_base = yy_base; + + yy_la_act = (unsigned short far *)LockResource (hRes_table); + yy_final = (short far *)(yy_la_act + Sizeof_yy_la_act); + yy_begin = (yy_state_t far *)(yy_final + Sizeof_yy_final); + yy_next = (yy_state_t far *)(yy_begin + Sizeof_yy_begin); + yy_check = (yy_state_t far *)(yy_next + Sizeof_yy_next); + yy_default = (yy_state_t far *)(yy_check + Sizeof_yy_check); + yy_base = (short far *)(yy_default + Sizeof_yy_default); + + + // call the standard yylex() code + + wReturnValue = win_yylex(); + + // unlock the resources + + UnlockResource (hRes_table); + + // and now free the resource + + FreeResource (hRes_table); + + // + // restore previously saved pointers + // + + yy_la_act = old_yy_la_act; + yy_final = old_yy_final; + yy_begin = old_yy_begin; + yy_next = old_yy_next; + yy_check = old_yy_check; + yy_default = old_yy_default; + yy_base = old_yy_base; + + return (wReturnValue); +} // end yylex() + +// The actual lex scanner +// yy_sbuf[0:yyleng-1] contains the states corresponding to yytext. +// yytext[0:yyleng-1] contains the current token. +// yytext[yyleng:yy_end-1] contains pushed-back characters. +// When the user action routine is active, +// save contains yytext[yyleng], which is set to '\0'. +// Things are different when YY_PRESERVE is defined. + +int +yy_scan::win_yylex() + +#else /* LEX_WINDOWS */ + +// The actual lex scanner +// yy_sbuf[0:yyleng-1] contains the states corresponding to yytext. +// yytext[0:yyleng-1] contains the current token. +// yytext[yyleng:yy_end-1] contains pushed-back characters. +// When the user action routine is active, +// save contains yytext[yyleng], which is set to '\0'. +// Things are different when YY_PRESERVE is defined. +int +yy_scan::yylex() +#endif /* LEX_WINDOWS */ + +{ + int c, i, yybase; + unsigned yyst; /* state */ + int yyfmin, yyfmax; /* yy_la_act indices of final states */ + int yyoldi, yyoleng; /* base i, yyleng before look-ahead */ + int yyeof; /* 1 if eof has already been read */ + +#line 375 "..\\..\\mkslexyacc\\etc\\yylex.cpp" + + +#ifdef YYEXIT + yyLexFatal = 0; +#endif + yyeof = 0; + i = yyleng; + YY_SCANNER(); + + yy_again: + if ((yyleng = i) > 0) { + yy_lastc = yytext[i-1]; // determine previous char + while (i > 0) // // scan previously token + if (yytext[--i] == YYNEWLINE) // fix yylineno + yylineno++; + } + yy_end -= yyleng; // adjust pushback + if (yy_end > 0) + memmove(yytext, yytext+yyleng, (size_t) yy_end); + i = 0; + + yy_contin: + yyoldi = i; + + /* run the state machine until it jams */ + yyst = yy_begin[yy_start + ((yy_lastc == YYNEWLINE) ? 1 : 0)]; + state[i] = (yy_state_t) yyst; + do { + YY_DEBUG("\n", yyst, i); + if (i >= size) { + YY_FATAL("Token buffer overflow"); +#ifdef YYEXIT + if (yyLexFatal) + return -2; +#endif + } /* endif */ + + /* get input char */ + if (i < yy_end) + c = yytext[i]; /* get pushback char */ + else if (!yyeof && (c = yygetc()) != EOF) { + yy_end = i+1; + yytext[i] = c; + } else /* c == EOF */ { + c = EOF; /* just to make sure... */ + if (i == yyoldi) { /* no token */ + yyeof = 0; + if (yywrap()) + return 0; + else + goto yy_again; + } else { + yyeof = 1; /* don't re-read EOF */ + break; + } + } + YY_DEBUG("\n", c, c); + + /* look up next state */ + while ((yybase = yy_base[yyst]+(unsigned char)c) > yy_nxtmax + || yy_check[yybase] != (yy_state_t) yyst) { + if (yyst == (unsigned int)yy_endst) + goto yy_jammed; + yyst = yy_default[yyst]; + } + yyst = yy_next[yybase]; + yy_jammed: ; + state[++i] = (yy_state_t) yyst; + } while (!(yyst == (unsigned int)yy_endst || YY_INTERACTIVE && + yy_base[yyst] > yy_nxtmax && yy_default[yyst] == yy_endst)); + + YY_DEBUG("\n", yyst, i); + if (yyst != (unsigned int)yy_endst) + ++i; + + yy_search: + /* search backward for a final state */ + while (--i > yyoldi) { + yyst = state[i]; + if ((yyfmin = yy_final[yyst]) < (yyfmax = yy_final[yyst+1])) + goto yy_found; /* found final state(s) */ + } + /* no match, default action */ + i = yyoldi + 1; + output(yytext[yyoldi]); + goto yy_again; + + yy_found: + YY_DEBUG("\n", yyst, i); + yyoleng = i; /* save length for REJECT */ + + // pushback look-ahead RHS, handling trailing context + if ((c = (int)(yy_la_act[yyfmin]>>9) - 1) >= 0) { + unsigned char *bv = yy_look + c*YY_LA_SIZE; + static unsigned char bits [8] = { + 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7 + }; + while (1) { + if (--i < yyoldi) { /* no / */ + i = yyoleng; + break; + } + yyst = state[i]; + if (bv[(unsigned)yyst/8] & bits[(unsigned)yyst%8]) + break; + } + } + + /* perform action */ + yyleng = i; + YY_USER(); + switch (yy_la_act[yyfmin] & 0777) { + case 0: +#line 109 "tokens.l" + { + BEGIN( globals ); + } + break; + case 1: +#line 114 "tokens.l" + { + BEGIN(INITIAL); + return TWP_SECTION; + } + break; + case 2: +#line 119 "tokens.l" + { TRACE_RETURN(TWP_ECHO); } + break; + case 3: +#line 122 "tokens.l" + { + lextrace(_T("eating spaces...")); /* eat spaces */ + } + break; + case 4: +#line 125 "tokens.l" + { + cParserHelper::IncrementLineNumber(); + lextrace(_T("eating line continuation...")); /* eat line continuations */ + } + break; + case 5: +#line 129 "tokens.l" + { + lextrace(_T("eating comment...")); + } + break; + case 6: +#line 138 "tokens.l" + { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::string"); + + // convert LPCSTR to TSTRING + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = cStringUtil::StrToTstr( yytext ); + + d.TraceDetail("--> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + + return TWP_GLOBAL_STRING; + } + break; + case 7: +#line 155 "tokens.l" + { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::qstring"); + + // get rid of beginning and trailing quotes + std::string strWithQuotes = yytext; + std::string str = strWithQuotes.substr(1, strWithQuotes.size() - 2); + + // convert any escape characters + TSTRING strW; + cParserUtil::InterpretEscapedString( str, strW ); + + d.TraceDetail(_T("read as --> <%s>\n"), strW.c_str()); + + // convert TSTRING to cParseString + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = strW; + + + d.TraceDetail("interpreted as --> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + return TWP_GLOBAL_STRING; + } + break; + case 8: +#line 182 "tokens.l" + { TRACE_RETURN(TWP_SEMICOLON); } + break; + case 9: +#line 183 "tokens.l" + { TRACE_RETURN(TWP_EQUALS); } + break; + case 10: +#line 185 "tokens.l" + { cParserHelper::IncrementLineNumber(); } + break; + case 11: +#line 186 "tokens.l" + { + std::string strError; + strError = FormatSyntaxError( yytext[0], "The global section only accepts statements of the form:\n variable = value;\n" ); + + // MKS defines yyerror with char*, for some stupid reason, + // so cast it away + yyerror( const_cast( strError.c_str() ) ); + } /* catches anything that cannot be deemed a variable definition and exits. */ + break; + case 12: +#line 196 "tokens.l" + { + lextrace(_T("eating spaces...")); /* eat spaces */ + } + break; + case 13: +#line 200 "tokens.l" + { + cParserHelper::IncrementLineNumber(); + lextrace(_T("eating line continuation...")); /* eat line continuations */ + } + break; + case 14: +#line 205 "tokens.l" + { + lextrace(_T("eating comment...")); + } + break; + case 15: +#line 209 "tokens.l" + { TRACE_RETURN(TWP_LBRACE); } + break; + case 16: +#line 210 "tokens.l" + { TRACE_RETURN(TWP_RBRACE); } + break; + case 17: +#line 213 "tokens.l" + { TRACE_RETURN(TWP_BANG); } + break; + case 18: +#line 215 "tokens.l" + { TRACE_RETURN(TWP_RARROW); } + break; + case 19: +#line 216 "tokens.l" + { TRACE_RETURN(TWP_EQUALS); } + break; + case 20: +#line 218 "tokens.l" + { TRACE_RETURN(TWP_SEMICOLON); } + break; + case 21: +#line 219 "tokens.l" + { TRACE_RETURN(TWP_LPAREN); } + break; + case 22: +#line 220 "tokens.l" + { TRACE_RETURN(TWP_RPAREN); } + break; + case 23: +#line 221 "tokens.l" + { TRACE_RETURN(TWP_COMMA); } + break; + case 24: +#line 222 "tokens.l" + { TRACE_RETURN(TWP_PIPE); } + break; + case 25: +#line 226 "tokens.l" + { TRACE_RETURN(TWP_DOLLAR); } + break; + case 26: +#line 227 "tokens.l" + { TRACE_RETURN(TWP_OROR); } + break; + case 27: +#line 230 "tokens.l" + { TRACE_RETURN(TWP_SECTION); } + break; + case 28: +#line 231 "tokens.l" + { TRACE_RETURN(TWP_IFHOST); } + break; + case 29: +#line 232 "tokens.l" + { TRACE_RETURN(TWP_ELSE); } + break; + case 30: +#line 233 "tokens.l" + { TRACE_RETURN(TWP_ENDIF); } + break; + case 31: +#line 234 "tokens.l" + { TRACE_RETURN(TWP_ERROR); } + break; + case 32: +#line 235 "tokens.l" + { TRACE_RETURN(TWP_ECHO); } + break; + case 33: +#line 236 "tokens.l" + { lextrace( _T( "@@end" ) ); return 0; } /* logical end of file */ + break; + case 34: +#line 239 "tokens.l" + { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::string"); + + // convert LPCSTR to TSTRING + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = cStringUtil::StrToTstr( yytext ); + + d.TraceDetail("--> <%s>\n", mpstring->c_str()); + + // attach to lval + yylval.mpString = mpstring; + + return TWP_STRING; + } + break; + case 35: +#line 256 "tokens.l" + { + // we must make copy of string, otherwise another lexeme will clobber it + cDebug d("\t\t\t\tlexer::qstring"); + + // get rid of beginning and trailing quotes + std::string strWithQuotes = yytext; + std::string str = strWithQuotes.substr(1, strWithQuotes.size() - 2); + + // convert any escape characters + TSTRING strW; + cParserUtil::InterpretEscapedString( str, strW ); + + d.TraceDetail(_T("read as --> <%s>\n"), strW.c_str()); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + cParserHelper::GetGenreInfo()->DoVarSubstitution( strW ); + } + + // convert TSTRING to cParseString + cParseString *mpstring = new cParseString; + ASSERT(mpstring); + *mpstring = strW; + + +#ifdef _DEBUG + TSTRING strDisplay = *mpstring; + cDisplayEncoder e; + e.Encode( strDisplay ); + d.TraceDetail("interpreted as --> <%s>\n", strDisplay.c_str()); +#endif // _DEBUG + + // attach to lval + yylval.mpString = mpstring; + return TWP_STRING; + } + break; + case 36: +#line 309 "tokens.l" + { cParserHelper::IncrementLineNumber(); } + break; + case 37: +#line 310 "tokens.l" + { + std::string strError; + strError = FormatSyntaxError( yytext[0] ); + + // MKS defines yyerror with char*, for some stupid reason, + // so cast it away + yyerror( const_cast( strError.c_str() ) ); + } /* catches anything else that's not in here and quits */ + break; + +#line 487 "..\\..\\mkslexyacc\\etc\\yylex.cpp" + + } + YY_SCANNER(); + i = yyleng; + goto yy_again; /* action fell though */ + + yy_reject: + YY_SCANNER(); + i = yyoleng; /* restore original yytext */ + if (++yyfmin < yyfmax) + goto yy_found; /* another final state, same length */ + else + goto yy_search; /* try shorter yytext */ + + yy_more: + YY_SCANNER(); + i = yyleng; + if (i > 0) + yy_lastc = yytext[i-1]; + goto yy_contin; +} + +/* + * user callable input/unput functions. + */ +void +yy_scan::yy_reset() +{ + YY_INIT(); + yylineno = 1; +} +/* get input char with pushback */ +int +yy_scan::input() +{ + int c; +#ifndef YY_PRESERVE + if (yy_end > yyleng) { + yy_end--; + memmove(yytext+yyleng, yytext+yyleng+1, + (size_t) (yy_end-yyleng)); + c = save; + YY_USER(); +#else + if (push < save+size) { + c = *push++; +#endif + } else + c = yygetc(); + yy_lastc = c; + if (c == YYNEWLINE) + yylineno++; + return c; +} + +/* pushback char */ +int +yy_scan::unput(int c) +{ +#ifndef YY_PRESERVE + if (yy_end >= size) { + YY_FATAL("Push-back buffer overflow"); + } else { + if (yy_end > yyleng) { + yytext[yyleng] = save; + memmove(yytext+yyleng+1, yytext+yyleng, + (size_t) (yy_end-yyleng)); + yytext[yyleng] = 0; + } + yy_end++; + save = c; +#else + if (push <= save) { + YY_FATAL("Push-back buffer overflow"); + } else { + *--push = c; +#endif + if (c == YYNEWLINE) + yylineno--; + } /* endif */ + return c; +} + +#line 321 "tokens.l" + + + diff --git a/src/twparser/yylex.h b/src/twparser/yylex.h new file mode 100644 index 0000000..a8be6d9 --- /dev/null +++ b/src/twparser/yylex.h @@ -0,0 +1,195 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtwparser.h" + + + +#ifndef yy_state_t +#define yy_state_t unsigned char +#endif +#define YYNEWLINE 10 + +#line 1 "..\\..\\mkslexyacc\\etc\\yylex.cpp" +// MKS LEX prototype scanner header +// Copyright 1991 by Mortice Kern Systems Inc. +// All rights reserved. + +// You can define YY_PRESERVE to get System V UNIX lex compatibility, +// if you need to change yytext[] in your user actions +// This is quite a bit slower, though, so the default is without + +#include // uses printf(), et cetera +#ifdef HAVE_STDARG_H +#include // uses va_list +#endif +#include // uses exit() +#include // uses memmove() + +#ifdef LEX_WINDOWS + +// define, if not already defined +// the flag YYEXIT, which will allow +// graceful exits from yylex() +// without resorting to calling exit(); + +#ifndef YYEXIT +#define YYEXIT 1 +#endif // YYEXIT + +// include the windows specific prototypes, macros, etc + +#include + +// the following is the handle to the current +// instance of a windows program. The user +// program calling yylex must supply this! + +#ifdef STRICT +extern HINSTANCE hInst; +#else +extern HANDLE hInst; +#endif + +#endif /* LEX_WINDOWS */ + +class yy_scan { +protected: + +#ifdef LEX_WINDOWS + + // protected member function for actual scanning + + int win_yylex(); + +#endif /* LEX_WINDOWS */ + + yy_state_t * state; // state buffer + int size; // length of state buffer + int mustfree; // set if space is allocated + int yy_end; // end of pushback + int yy_start; // start state + int yy_lastc; // previous char +#ifdef YYEXIT + int yyLexFatal; // Lex Fatal Error Flag +#endif // YYEXIT +#ifndef YY_PRESERVE // efficient default push-back scheme + char save; // saved yytext[yyleng] +#else // slower push-back for yytext mungers + char *save; // saved yytext[] + char *push; +#endif + +public: + char *yytext; // yytext text buffer + FILE *yyin; // input stream + FILE *yyout; // output stream + int yylineno; // line number + int yyleng; // yytext token length + + yy_scan(int = 100); // constructor for this scanner + // default token & pushback size is 100 bytes + yy_scan(int, char*, char*, yy_state_t*); + // constructor when tables are given + + virtual ~yy_scan(); // destructor + + int yylex(); // begin a scan + + virtual int yygetc() { // scanner source of input characters + return getc(yyin); + } + + virtual int yywrap() { return 1; } // EOF processing + + virtual void yyerror(char *,...); // print error message + + virtual void output(int c) { putc(c, yyout); } + +#ifdef YYEXIT + virtual void YY_FATAL(char * msg) { // print message and set error flag + yyerror(msg); yyLexFatal = 1; + } +#else // YYEXIT + virtual void YY_FATAL(char * msg) { // print message and stop + yyerror(msg); exit(1); + } +#endif // YYEXIT + virtual void ECHO() { // print matched input + fputs((const char *) yytext, yyout); + } + int input(); // user-callable get-input + int unput(int c); // user-callable unput character + void yy_reset(); // reset scanner + void setinput(FILE * in) { // switch input streams + yyin = in; + } + void setoutput(FILE * out) { // switch output + yyout = out; + } + void NLSTATE() { yy_lastc = YYNEWLINE; } + void YY_INIT() { + yy_start = 0; + yyleng = yy_end = 0; + yy_lastc = YYNEWLINE; + } + void YY_USER() { // set up yytext for user +#ifndef YY_PRESERVE + save = yytext[yyleng]; +#else + size_t n = yy_end - yyleng; + push = save+size - n; + if (n > 0) + memmove(push, yytext+yyleng, n); +#endif + yytext[yyleng] = 0; + } + void YY_SCANNER() { // set up yytext for scanner +#ifndef YY_PRESERVE + yytext[yyleng] = save; +#else + size_t n = save+size - push; + if (n > 0) + memmove(yytext+yyleng, push, n); + yy_end = yyleng + n; +#endif + } + void yyless(int n) { // trim input to 'n' bytes + if (n >= 0 && n <= yy_end) { + YY_SCANNER(); + yyleng = n; + YY_USER(); + } + } + void yycomment(char *const mat); // skip comment input + int yymapch(int delim, int escape); // map C escapes +} ; + diff --git a/src/twparser/yyparse.cpp b/src/twparser/yyparse.cpp new file mode 100644 index 0000000..90ae843 --- /dev/null +++ b/src/twparser/yyparse.cpp @@ -0,0 +1,1486 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/* ..\. -LC -o ..\twparser\yyparse.cpp -P ..\..\mkslexyacc\etc\yyparse.cpp -D yyparse.h policy.y */ +#line 74 "policy.y" + + +#include "stdtwparser.h" + +#include "core/debug.h" +#include "parserhelper.h" +#include "genreparseinfo.h" +#include "policyparser.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fconameinfo.h" +#include "fco/parsergenreutil.h" +#include "fco/fconametranslator.h" +#include "core/usernotify.h" + +#ifndef YYNEWLINE +# include "parser/yylex.h" +# include "parser/yyparse.h" +#endif + + +// global variables +int yaccdebuglevel; + +// in MKS Yacc in C++ mode, we need to explicitly declare yylavl +YYSTYPE yylval; + + +static TSTRING ConcatenateStrings( const std::list* plist ) +{ + TSTRING strRet; + for( std::list::const_iterator i = plist->begin(); i != plist->end(); i++ ) + strRet += *i; + return strRet; +} + +static std::list* MergeIntoList( std::list* plistLHS, const std::list* plistRHS ) +{ + for( std::list::const_iterator i = plistRHS->begin(); i != plistRHS->end(); i++ ) + plistLHS->push_back( *i ); + return plistLHS; +} + +extern YYSTYPE yylval; +#if YYDEBUG +enum YY_Types { YY_t_NoneDefined, YY_t_mpString, YY_t_mpNode, YY_t_mpAttr, YY_t_mpAttrList, YY_t_mpStringList +}; +#endif +#if YYDEBUG +yyTypedRules yyRules[] = { + { "&00: %18 &00", 0}, + { "%18: %19", 0}, + { "%19: %20", 0}, + { "%19:", 0}, + { "%20: %20 %21", 0}, + { "%20: %21", 0}, + { "%21: %22 &07", 0}, + { "%21: %23 &07", 0}, + { "%21: %24 &07", 0}, + { "%21: &07", 0}, + { "%21: %25", 0}, + { "%21: %26", 0}, + { "%27:", 0}, + { "%26: &03 %04 &04 &08 %27 %19 &09", 0}, + { "%28:", 0}, + { "%25: &19 %16 %28 %19 %29 &21", 0}, + { "%25: &18 %09", 0}, + { "%25: &23 %09", 0}, + { "%25: &22 %09", 0}, + { "%16: %16 &29 %15", 5}, + { "%16: %15", 5}, + { "%30:", 0}, + { "%29: &20 %30 %19", 0}, + { "%29:", 0}, + { "%22: %13 &33 %10", 0}, + { "%23: %14 &33 %11", 0}, + { "%24: %06 &17 %01", 0}, + { "%24: &13 %06", 0}, + { "%01: %17 %05", 2}, + { "%05: &03 %04 &04", 4}, + { "%05:", 4}, + { "%04: %03 %31", 4}, + { "%03: %03 &02 %02", 4}, + { "%03: %02", 4}, + { "%02: %07 &33 %08", 3}, + { "%31: &02", 0}, + { "%31:", 0}, + { "%12: &12 &03 %13 &04", 1}, + { "%17: %10", 1}, + { "%07: %09", 1}, + { "%08: %10", 1}, + { "%06: %10", 5}, + { "%06: %10 &11 %10", 5}, + { "%15: %09", 1}, + { "%13: &06", 1}, + { "%10: %10 %09", 5}, + { "%10: %09", 5}, + { "%11: %11 %14", 5}, + { "%11: %14", 5}, + { "%09: &06", 1}, + { "%09: %12", 1}, + { "%14: &34", 1}, +{ "$accept", 0},{ "error", 0} +}; +yyNamedType yyTokenTypes[] = { + { "$end", 0, 0}, + { "error", 256, 0}, + { "TWP_COMMA", 257, 0}, + { "TWP_LPAREN", 258, 0}, + { "TWP_RPAREN", 259, 0}, + { "TWP_COMMENT", 260, 0}, + { "TWP_STRING", 261, 1}, + { "TWP_SEMICOLON", 262, 0}, + { "TWP_LBRACE", 263, 0}, + { "TWP_RBRACE", 264, 0}, + { "TWP_DEFAULT", 265, 0}, + { "TWP_PIPE", 266, 0}, + { "TWP_DOLLAR", 267, 0}, + { "TWP_BANG", 268, 0}, + { "TWP_PLUS", 269, 0}, + { "TWP_MINUS", 270, 0}, + { "TWP_DQUOTE", 271, 0}, + { "TWP_RARROW", 272, 0}, + { "TWP_SECTION", 273, 0}, + { "TWP_IFHOST", 274, 0}, + { "TWP_ELSE", 275, 0}, + { "TWP_ENDIF", 276, 0}, + { "TWP_ECHO", 277, 0}, + { "TWP_ERROR", 278, 0}, + { "TWP_DEFINE", 279, 0}, + { "TWP_UNDEF", 280, 0}, + { "TWP_CONTENTS", 281, 0}, + { "TWP_DBASEVERSION", 282, 0}, + { "TWP_ANDAND", 283, 0}, + { "TWP_OROR", 284, 0}, + { "TWP_BSLASH", 285, 0}, + { "TWP_ESCCHAR", 286, 0}, + { "TWP_QSTRING", 287, 0}, + { "TWP_EQUALS", 288, 0}, + { "TWP_GLOBAL_STRING", 289, 1} + +}; +#endif +static short yydef[] = { + + 65535, 65531, 9, 53, 65527, 3, 65523, 10, 7, 65519, + 5, 4, 65515, 50, 65509, 8, 65505, -35 +}; +static short yyex[] = { + + 0, 52, 65535, 1, 288, 18, 65535, 13, 0, 0, + 65535, 1, 259, 49, 65535, 1, 262, 6, 65535, 1, + 275, 52, 276, 52, 65535, 1, 276, 51, 65535, 1, + 264, 52, 65535, 1, 276, 52, 65535, 1 +}; +static short yyact[] = { + + 65499, 65534, 65455, 65490, 65491, 65497, 65498, 65495, 65496, 65489, + 289, 278, 277, 274, 273, 268, 267, 262, 261, 258, + 65487, 65503, 65490, 267, 266, 261, 65504, 258, 65487, 65490, + 267, 261, 65505, 272, 65506, 288, 65507, 288, 65461, 262, + 65460, 262, 65459, 262, 65482, 261, 65489, 289, 65511, 284, + 65512, 288, 65522, 257, 65513, 259, 65479, 259, 65514, 258, + 65462, 263, 65470, 275, 65474, 259, 65464, 276, 65463, 264, -1 +}; +static short yypact[] = { + + 10, 20, 23, 10, 44, 49, 53, 30, 30, 59, + 47, 30, 10, 30, 63, 30, 10, 10, 69, 67, + 65, 30, 61, 30, 30, 57, 55, 51, 30, 47, + 30, 45, 30, 43, 41, 39, 30, 30, 30, 30, + 30, 37, 35, 33, 30, 27 +}; +static short yygo[] = { + + 65471, 65476, 65477, 13, 65529, 65515, 65509, 21, 65473, 65472, + 65492, 44, 65508, 65478, 65483, 65483, 65483, 65483, 65480, 65483, + 65480, 65481, 65480, 65481, 65465, 65466, 65467, 65484, 40, 39, + 38, 37, 36, 24, 21, 15, 13, 11, 8, 7, + 2, 65520, 65524, 65527, 65528, 65533, 32, 30, 28, 23, + 65525, 65488, 65510, 65494, 31, 65485, 65486, 65493, 29, 10, + 65468, 65469, 24, 65530, 65526, 65531, 65521, 65517, 65452, 65458, + 17, 16, 12, 65532, 65457, 65456, 3, 65502, 65501, 65500, + 65454, 65453, 65519, 65523, 65516, 65518, 65475, -1 +}; +static short yypgo[] = { + + 0, 0, 0, 83, 77, 78, 8, 64, 13, 10, + 10, 57, 27, 27, 50, 50, 45, 45, 53, 61, + 12, 51, 2, 4, 4, 6, 8, 0, 79, 79, + 85, 63, 63, 80, 80, 80, 80, 81, 82, 75, + 75, 75, 65, 73, 73, 75, 75, 75, 84, 86, + 86, 84, 69, 69, 0 +}; +static short yyrlen[] = { + + 0, 0, 0, 0, 3, 3, 0, 1, 1, 1, + 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, + 1, 4, 3, 1, 3, 2, 3, 2, 2, 3, + 0, 1, 3, 2, 2, 2, 6, 7, 0, 2, + 2, 2, 1, 2, 1, 1, 1, 1, 3, 0, + 1, 0, 0, 1, 2 +}; +#define YYS0 0 +#define YYDELTA 35 +#define YYNPACT 46 +#define YYNDEF 18 + +#define YYr52 0 +#define YYr53 1 +#define YYr54 2 +#define YYr14 3 +#define YYr24 4 +#define YYr25 5 +#define YYr30 6 +#define YYr38 7 +#define YYr40 8 +#define YYr41 9 +#define YYr42 10 +#define YYr51 11 +#define YYr50 12 +#define YYr49 13 +#define YYr48 14 +#define YYr47 15 +#define YYr46 16 +#define YYr45 17 +#define YYr44 18 +#define YYr43 19 +#define YYr39 20 +#define YYr37 21 +#define YYr34 22 +#define YYr33 23 +#define YYr32 24 +#define YYr31 25 +#define YYr29 26 +#define YYr28 27 +#define YYr27 28 +#define YYr26 29 +#define YYr21 30 +#define YYr20 31 +#define YYr19 32 +#define YYr18 33 +#define YYr17 34 +#define YYr16 35 +#define YYr15 36 +#define YYr13 37 +#define YYr12 38 +#define YYr8 39 +#define YYr7 40 +#define YYr6 41 +#define YYrACCEPT YYr52 +#define YYrERROR YYr53 +#define YYrLR2 YYr54 +#if YYDEBUG +char * yysvar[] = { + "$accept", + "spec_masks", + "attribute", + "attribute_list", + "attribute_list_with_opt_trailing_comma", + "opt_spec_attributes", + "fco_name", + "attribute_name", + "attribute_value", + "string", + "multi_string", + "global_multi_string", + "variable", + "variable_name", + "global_string", + "host_name", + "host_name_list", + "prop_vector", + "policy", + "opt_statement_list", + "statement_list", + "statement", + "variable_assignment", + "global_variable_assignment", + "rule", + "directive_block", + "scoped_block", + "$12", + "$14", + "opt_else_host", + "$21", + "opt_comma", + 0 +}; +short yyrmap[] = { + + 52, 53, 54, 14, 24, 25, 30, 38, 40, 41, + 42, 51, 50, 49, 48, 47, 46, 45, 44, 43, + 39, 37, 34, 33, 32, 31, 29, 28, 27, 26, + 21, 20, 19, 18, 17, 16, 15, 13, 12, 8, + 7, 6, 1, 4, 5, 9, 10, 11, 22, 36, + 35, 23, 3, 2, 0 +}; +short yysmap[] = { + + 0, 4, 5, 23, 25, 39, 43, 49, 52, 53, + 56, 57, 59, 61, 69, 70, 77, 79, 81, 76, + 74, 65, 63, 60, 58, 51, 44, 41, 33, 32, + 31, 29, 28, 21, 20, 19, 15, 14, 13, 12, + 11, 10, 9, 8, 7, 6, 1, 2, 26, 55, + 67, 3, 27, 50, 37, 40, 64, 71, 42, 72, + 62, 78, 66, 30, 54, 75, 38, 68, 34, 35, + 36, 80, 83, 73, 45, 46, 47, 24, 48, 22, + 18, 17, 16, 82 +}; +int yy_parse::yyntoken = 35; +int yy_parse::yynvar = 32; +int yy_parse::yynstate = 84; +int yy_parse::yynrule = 55; +#endif + + + +#line 2 "..\\..\\mkslexyacc\\etc\\yyparse.cpp" +// C++ YACC parser code +// Copyright 1991 by Mortice Kern Systems Inc. All rights reserved. +// +// If YYDEBUG is defined as 1 and yy_parse::yydebug is set to 1, +// yyparse() will print a travelogue of its actions as it reads +// and parses input. +// +// YYSYNC can be defined to cause yyparse() to attempt to always +// hold a lookahead token + +const int YY_MIN_STATE_NUM = 20; // not useful to be too small! + +#if YYDEBUG +#ifdef YYTRACE +long * yy_parse::States = yyStates; +#endif +yyTypedRules * yy_parse::Rules = yyRules; +yyNamedType * yy_parse::TokenTypes = yyTokenTypes; + +#define YY_TRACE(fn) { done = 0; fn(); if (done) YYRETURN(-1); } +#endif + +// Constructor for yy_parse: user-provided tables +yy_parse::yy_parse(int sz, short * states, YYSTYPE * stack) +{ + mustfree = 0; + if ((size = sz) < YY_MIN_STATE_NUM + || (stateStack = states) == (short *) 0 + || (valueStack = stack) == (YYSTYPE *) 0) { + fprintf(stderr,"Bad state/stack given"); + exit(1); + } + reset = 1; // force reset +#if YYDEBUG + yydebug = 0; + typeStack = new short[size+1]; + if (typeStack == (short *) 0) { + fprintf(stderr,"Cannot allocate typeStack"); + exit(1); + } +#endif +} +// Constructor for yy_parse: allocate tables with new +yy_parse::yy_parse(int sz) +{ + size = sz; + reset = 1; // force reset + mustfree = 1; // delete space in deconstructor +#if YYDEBUG + yydebug = 0; + typeStack = new short[size+1]; +#endif + stateStack = new short[size+1]; + valueStack = new YYSTYPE[size+1]; + + if (stateStack == (short *) 0 || valueStack == (YYSTYPE *) 0 +#if YYDEBUG + || typeStack == (short *) 0 +#endif + ) { + fprintf(stderr,"Not enough space for parser stacks"); + exit(1); + } +} +// Destructor for class yy_parse +// Free up space +yy_parse::~yy_parse() +{ + if (mustfree) { + delete stateStack; + delete valueStack; + } + stateStack = (short *) 0; +#if YYDEBUG + delete typeStack; +#endif +} + +#ifdef YACC_WINDOWS + +// The initial portion of the yacc parser. +// In an windows environment, it will load the desired +// resources, obtain pointers to them, and then call +// the protected member win_yyparse() to acutally begin the +// parsing. When complete, win_yyparse() will return a +// value back to our new yyparse() function, which will +// record that value temporarily, release the resources +// from global memory, and finally return the value +// back to the caller of yyparse(). + +int +yy_parse::yyparse(yy_scan* ps) +{ + int wReturnValue; + HANDLE hRes_table; + short far *old_yydef; // the following are used for saving + short far *old_yyex; // the current pointers + short far *old_yyact; + short far *old_yypact; + short far *old_yygo; + short far *old_yypgo; + short far *old_yyrlen; + + // the following code will load the required + // resources for a Windows based parser. + + hRes_table = LoadResource (hInst, + FindResource (hInst, "UD_RES_yyYACC", "yyYACCTBL")); + + // return an error code if any + // of the resources did not load + + if (hRes_table == (HANDLE)NULL) + return (1); + + // the following code will lock the resources + // into fixed memory locations for the parser + // (also, save away the old pointer values) + + old_yydef = yydef; + old_yyex = yyex; + old_yyact = yyact; + old_yypact = yypact; + old_yygo = yygo; + old_yypgo = yypgo; + old_yyrlen = yyrlen; + + yydef = (short far *)LockResource (hRes_table); + yyex = (short far *)(yydef + Sizeof_yydef); + yyact = (short far *)(yyex + Sizeof_yyex); + yypact = (short far *)(yyact + Sizeof_yyact); + yygo = (short far *)(yypact + Sizeof_yypact); + yypgo = (short far *)(yygo + Sizeof_yygo); + yyrlen = (short far *)(yypgo + Sizeof_yypgo); + + // call the official yyparse() function + + wReturnValue = win_yyparse (ps); + + // unlock the resources + + UnlockResource (hRes_table); + + // and now free the resource + + FreeResource (hRes_table); + + // + // restore previous pointer values + // + + yydef = old_yydef; + yyex = old_yyex; + yyact = old_yyact; + yypact = old_yypact; + yygo = old_yygo; + yypgo = old_yypgo; + yyrlen = old_yyrlen; + + return (wReturnValue); +} // end yyparse() + + +// The parser proper. +// Note that this code is reentrant; you can return a value +// and then resume parsing by recalling yyparse(). +// Call yyreset() before yyparse() if you want a fresh start + +int +yy_parse::win_yyparse(yy_scan* ps) + +#else /* YACC_WINDOWS */ + +// The parser proper. +// Note that this code is reentrant; you can return a value +// and then resume parsing by recalling yyparse(). +// Call yyreset() before yyparse() if you want a fresh start +int +yy_parse::yyparse(yy_scan* ps) + +#endif /* YACC_WINDOWS */ + +{ +#ifdef YACC_WINDOWS + short far *yyp; // needed as res tables locked in far memory + short far *yyq; +#else + short * yyp, * yyq; // table lookup +#endif /* YACC_WINDOWS */ + int yyj; +#if YYDEBUG + int yyruletype = 0; +#endif + + if ((scan = ps) == (yy_scan *) 0) { // scanner + fprintf(stderr,"No scanner"); + exit(1); + } + + if (reset) { // start new parse + yynerrs = 0; + yyerrflag = 0; + yyps = stateStack; + yypv = valueStack; +#if YYDEBUG + yytp = typeStack; +#endif + yystate = YYS0; + yyclearin(); + reset = 0; + } else // continue saved parse + goto yyNext; // after action + +yyStack: + if (++yyps > &stateStack[size]) { + scan->yyerror("Parser stack overflow"); + YYABORT; + } + *yyps = yystate; /* stack current state */ + *++yypv = yyval; /* ... and value */ +#if YYDEBUG + if (yydebug) { + *++yytp = yyruletype; /* ... and type */ + YY_TRACE(yyShowState) + } +#endif + + /* + * Look up next action in action table. + */ +yyEncore: +#ifdef YYSYNC + if (yychar < 0) { + if ((yychar = scan->yylex()) < 0) { + if (yychar == -2) YYABORT; + yychar = 0; + } /* endif */ + yylval = ::yylval; +#if YYDEBUG + if (yydebug) + yyShowRead(); // show new input token +#endif + } +#endif +#ifdef YACC_WINDOWS + if (yystate >= Sizeof_yypact) /* simple state */ +#else /* YACC_WINDOWS */ + if (yystate >= (int)sizeof yypact/(int)sizeof yypact[0]) /* simple state */ +#endif /* YACC_WINDOWS */ + yyi = yystate - YYDELTA; /* reduce in any case */ + else { + if(*(yyp = &yyact[yypact[yystate]]) >= 0) { + /* Look for a shift on yychar */ +#ifndef YYSYNC + if (yychar < 0) { + if ((yychar = scan->yylex()) < 0) { + if (yychar == -2) YYABORT; + yychar = 0; + } /* endif */ + yylval = ::yylval; +#if YYDEBUG + if (yydebug) + yyShowRead(); // show new input token +#endif + } +#endif + yyq = yyp; + yyi = yychar; + while (yyi < *yyp++) + ; + if (yyi == yyp[-1]) { + yystate = yyneg(yyq[yyq-yyp]); +#if YYDEBUG + if (yydebug) { + yyruletype = yyGetType(yychar); + YY_TRACE(yyShowShift) + } +#endif + yyval = yylval; /* stack value */ + yyclearin(); /* clear token */ + if (yyerrflag) + yyerrflag--; /* successful shift */ + goto yyStack; + } + } + + /* + * Fell through - take default action + */ + +#ifdef YACC_WINDOWS + if (yystate >= Sizeof_yydef) /* simple state */ +#else /* YACC_WINDOWS */ + if (yystate >= (int)sizeof yydef /(int)sizeof yydef[0]) +#endif /* YACC_WINDOWS */ + goto yyError; + if ((yyi = yydef[yystate]) < 0) { /* default == reduce? */ + + /* Search exception table */ + yyp = &yyex[yyneg(yyi)]; +#ifndef YYSYNC + if (yychar < 0) { + if ((yychar = scan->yylex()) < 0) { + if (yychar == -2) YYABORT; + yychar = 0; + } /* endif */ + yylval = ::yylval; +#if YYDEBUG + if (yydebug) + yyShowRead(); // show new input token +#endif + } +#endif + while((yyi = *yyp) >= 0 && yyi != yychar) + yyp += 2; + yyi = yyp[1]; + } + } + + yyj = yyrlen[yyi]; + +#if YYDEBUG + if (yydebug) { + npop = yyj; rule = yyi; + YY_TRACE(yyShowReduce) + yytp -= yyj; + } +#endif + yyps -= yyj; /* pop stacks */ + yypvt = yypv; /* save top */ + yypv -= yyj; + yyval = yypv[1]; /* default action $ = $1 */ +#if YYDEBUG + if (yydebug) + yyruletype = yyRules[yyrmap[yyi]].type; +#endif + switch (yyi) { /* perform semantic action */ + +case YYr6: { /* statement : variable_assignment TWP_SEMICOLON */ +#line 194 "policy.y" + cParserHelper::IncrementScopeStatementCount(); +} break; + +case YYr7: { /* statement : global_variable_assignment TWP_SEMICOLON */ +#line 195 "policy.y" + cParserHelper::IncrementScopeStatementCount(); +} break; + +case YYr8: { /* statement : rule TWP_SEMICOLON */ +#line 196 "policy.y" + cParserHelper::IncrementScopeStatementCount(); +} break; + +case YYr12: { /* scoped_block : TWP_LPAREN attribute_list_with_opt_trailing_comma TWP_RPAREN TWP_LBRACE */ +#line 204 "policy.y" + + cDebug d("Parse::scope"); + + // create new scope + cAttrScopeInfo* pScopeInfo = new cAttrScopeInfo; + + // init scope info + pScopeInfo->SetAttributes( yypvt[-2].mpAttrList ); + + // push onto scope stack + cParserHelper::PushScope( pScopeInfo ); + d.TraceDebug("push\n"); + +} break; + +case YYr13: { /* scoped_block : TWP_LPAREN attribute_list_with_opt_trailing_comma TWP_RPAREN TWP_LBRACE $12 opt_statement_list TWP_RBRACE */ +#line 218 "policy.y" + + if( 0 == cParserHelper::GetScopeStatementCount() && iUserNotify::GetInstance()->GetVerboseLevel() == iUserNotify::V_VERBOSE ) + { + eParserNoStatementsInScope e; + e.SetFatality( false ); + cParserHelper::GetErrorBucket()->AddError( e ); + } + + cDebug d("Parse::scope"); + cParserHelper::PopScope(); + d.TraceDebug("pop\n"); + +} break; + +case YYr14: { /* directive_block : TWP_IFHOST host_name_list */ +#line 234 "policy.y" + + cDebug d("Parse::#ifhost"); + + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + if( cParserUtil::AnyOfTheseHostsExists( yypvt[0].mpStringList ) ) + { + cPreprocessor::PushState( cPreprocessor::STATE_ACCEPT ); + } + else + { + cPreprocessor::PushState( cPreprocessor::STATE_IGNORE ); + } + d.TraceDebug(_T("\n")); + } + else + { + cPreprocessor::PushState( cPreprocessor::STATE_IGNORE ); + d.TraceDebug(_T("ignoring ifhost\n")); + } + +} break; + +case YYr15: { /* directive_block : TWP_IFHOST host_name_list $14 opt_statement_list opt_else_host TWP_ENDIF */ +#line 257 "policy.y" + + cDebug d("Parse::#endif"); + cPreprocessor::PopState(); + + delete yypvt[-4].mpStringList; + +} break; + +case YYr16: { /* directive_block : TWP_SECTION string */ +#line 264 "policy.y" + + cDebug d("Parse::#section"); + + if( ! ( cPreprocessor::AtTopLevel() && cParserHelper::AtTopScope() ) ) + throw eParserSectionInsideBlock( *yypvt[0].mpString ); + + cParserHelper::SetSection( *yypvt[0].mpString ); + + delete yypvt[0].mpString; + +} break; + +case YYr17: { /* directive_block : TWP_ERROR string */ +#line 275 "policy.y" + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT && !cParserHelper::ParseOnly() ) + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, yypvt[0].mpString->c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("\n") ); + YYRETURN(-1); + } + + delete yypvt[0].mpString; + +} break; + +case YYr18: { /* directive_block : TWP_ECHO string */ +#line 286 "policy.y" + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT && !cParserHelper::ParseOnly() ) + { + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, yypvt[0].mpString->c_str()); + iUserNotify::GetInstance()->Notify( iUserNotify::V_NORMAL, _T("\n") ); + } + + delete yypvt[0].mpString; + +} break; + +case YYr19: { /* host_name_list : host_name_list TWP_OROR host_name */ +#line 299 "policy.y" + + yyval.mpStringList = yypvt[-2].mpStringList; + yyval.mpStringList->push_back( *yypvt[0].mpString ); + +} break; + +case YYr20: { /* host_name_list : host_name */ +#line 304 "policy.y" + + yyval.mpStringList = new cParseStringList; + yyval.mpStringList->push_back( *yypvt[0].mpString ); + +} break; + +case YYr21: { /* opt_else_host : TWP_ELSE */ +#line 312 "policy.y" + + cDebug d("Parse::#else"); + + if( cPreprocessor::GetLastState() == cPreprocessor::STATE_ACCEPT ) + { + cPreprocessor::ToggleTopState(); + d.TraceDebug(_T("\n")); + } + else + { + d.TraceDebug(_T("ignoring #else\n")); + } + + +} break; + +case YYr24: { /* variable_assignment : variable_name TWP_EQUALS multi_string */ +#line 332 "policy.y" + + cDebug d("Parse::variable_assignment"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring variable assignment\n")); + } + else + { + TSTRING strVal = ConcatenateStrings( yypvt[0].mpStringList ); + d.TraceDebug("*** assigning <%s> to <%s>\n", yypvt[-2].mpString->c_str(), strVal.c_str() ); + cParserHelper::GetGenreInfo()->InsertVariable( *yypvt[-2].mpString, strVal ); + } + + delete yypvt[-2].mpString; + delete yypvt[0].mpStringList; + +} break; + +case YYr25: { /* global_variable_assignment : global_string TWP_EQUALS global_multi_string */ +#line 353 "policy.y" + + cDebug d("Parse::global variable_assignment"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring global variable assignment\n")); + } + else + { + TSTRING strVal = ConcatenateStrings( yypvt[0].mpStringList ); + d.TraceDebug("*** assigning <%s> to <%s>\n", yypvt[-2].mpString->c_str(), strVal.c_str() ); + cParserHelper::InsertGlobalVariable( *yypvt[-2].mpString, strVal ); + } + + delete yypvt[-2].mpString; + delete yypvt[0].mpStringList; + +} break; + +case YYr26: { /* rule : fco_name TWP_RARROW spec_masks */ +#line 374 "policy.y" + + cDebug d("Parse::rule(fco_name TWP_RARROW spec_masks)"); + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring rule\n")); + } + else + { + // bind to children + cParseStringList *pnamelist = yypvt[-2].mpStringList; + cParseRule *pnode = yypvt[0].mpNode; + cFCOName fcoName; + + // create the fco name from string + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + pGU->InterpretFCOName( *pnamelist, fcoName ); + + if( ! pGU->IsAbsolutePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringRaw( fcoName ) ) ) + throw eParserRelativePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + else if( cParserHelper::GetGenreInfo()->RulePointAlreadyDefined( fcoName ) ) + throw eParserPointAlreadyDefined( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + + // assign parse node the name, attributes + pnode->SetName( fcoName ); + + d.TraceDebug("*** rule(%s: %d specifiers, default=%s) (%d named attributes) (is%s case sensitive)\n", + pnode->GetName().AsString().c_str(), pnode->GetNumSpecMasks(), + pnode->GetDefSpecMask().GetPropVectorString().c_str(), + pnode->GetNumNamedAttrs(), + iTWFactory::GetInstance()->GetNameInfo()->IsCaseSensitive() ? "" : " not" ); + + pnode->Dump(); + + // add to our lists + cParserHelper::GetGenreInfo()->AddStopPoint( fcoName ); + cParserHelper::GetGenreInfo()->AddRule( pnode ); + } + + delete yypvt[-2].mpStringList; + + +} break; + +case YYr27: { /* rule : TWP_BANG fco_name */ +#line 416 "policy.y" + + cDebug d("Parse::rule(!fconame)"); + + if( cPreprocessor::GetState() == cPreprocessor::STATE_IGNORE ) + { + d.TraceDebug(_T(" ignoring rule\n")); + } + else + { + // create the fco name from string + cFCOName fcoName; + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + pGU->InterpretFCOName( *yypvt[0].mpStringList, fcoName ); + + if( ! pGU->IsAbsolutePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringRaw( fcoName ) ) ) + throw eParserRelativePath( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + if( cParserHelper::GetGenreInfo()->RulePointAlreadyDefined( fcoName ) ) + throw eParserPointAlreadyDefined( iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( fcoName ) ); + + d.TraceDebug( "*** omit(%s)\n", fcoName.AsString().c_str() ); + + // add to stop list + cParserHelper::GetGenreInfo()->AddStopPoint( fcoName ); + } + + delete yypvt[0].mpStringList; + +} break; + +case YYr28: { /* spec_masks : prop_vector opt_spec_attributes */ +#line 447 "policy.y" + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); + TSTRING strDefault = _T("default"); + cParseRule* pNode = new cParseRule( cParseSpecMask( strDefault, *yypvt[-1].mpString, pGU ) ); + + pNode->SetAttrList( yypvt[0].mpAttrList ); + yypvt[0].mpAttrList->MergeNoOverwrite( cParserHelper::GetGlobalAttrList() ); + + yyval.mpNode = pNode; + } + + delete yypvt[-1].mpString; + + + +} break; + +case YYr29: { /* opt_spec_attributes : TWP_LPAREN attribute_list_with_opt_trailing_comma TWP_RPAREN */ +#line 485 "policy.y" + + yyval.mpAttrList = yypvt[-1].mpAttrList; + +} break; + +case YYr30: { /* opt_spec_attributes : */ +#line 489 "policy.y" + + yyval.mpAttrList = new cParseNamedAttrList; + +} break; + +case YYr31: { /* attribute_list_with_opt_trailing_comma : attribute_list opt_comma */ +#line 515 "policy.y" + + yyval.mpAttrList = yypvt[-1].mpAttrList; + +} break; + +case YYr32: { /* attribute_list : attribute_list TWP_COMMA attribute */ +#line 522 "policy.y" + + cDebug d("Parse::attribute_list"); + ASSERT( yypvt[-2].mpAttrList && yypvt[0].mpAttr ); + + // add attribute to list + yypvt[-2].mpAttrList->Add( yypvt[0].mpAttr ); + d.TraceDebug("added attribute (%s=%s)\n", yypvt[0].mpAttr->GetName().c_str(), yypvt[0].mpAttr->GetValue().c_str()); + + yyval.mpAttrList = yypvt[-2].mpAttrList; + + + +} break; + +case YYr33: { /* attribute_list : attribute */ +#line 535 "policy.y" + + cDebug d("Parse::attribute_list"); + + cParseNamedAttrList *pAttrList = new cParseNamedAttrList; ASSERT( pAttrList ); + + pAttrList->Add( yypvt[0].mpAttr ); + d.TraceDebug("added attribute (%s=%s)\n", yypvt[0].mpAttr->GetName().c_str(), yypvt[0].mpAttr->GetValue().c_str()); + + yyval.mpAttrList = pAttrList; + +} break; + +case YYr34: { /* attribute : attribute_name TWP_EQUALS attribute_value */ +#line 548 "policy.y" + + cDebug d("Parse::attribute"); + + cParseNamedAttr *pAttr = new cParseNamedAttr( *yypvt[-2].mpString, *yypvt[0].mpString ); + ASSERT(pAttr); + + d.TraceDebug("attribute (%s=%s)\n", yypvt[-2].mpString->c_str(), yypvt[0].mpString->c_str()); + yyval.mpAttr = pAttr; + + + delete yypvt[-2].mpString; + delete yypvt[0].mpString; + +} break; + +case YYr37: { /* variable : TWP_DOLLAR TWP_LPAREN variable_name TWP_RPAREN */ +#line 618 "policy.y" + + cDebug d( " parser::variable" ); + + cParseString* pVarValue = new cParseString; + + if( cPreprocessor::GetState() == cPreprocessor::STATE_ACCEPT ) + { + // we want to replace the keyword with its value, (e.g. replacing ReadOnly + // with "pingus" (or whatever readonly means). So it is a rote replacement. + if( ! cParserHelper::GetGenreInfo()->LookupVariable( *yypvt[-1].mpString, *pVarValue ) ) + throw eParserUseUndefVar( *yypvt[-1].mpString ); + + // return the lval + d.TraceDetail("--(STRING)--> got variable (%s) mapped to (%s)\n", + yypvt[-1].mpString->c_str(), + pVarValue->c_str()); + } + + yyval.mpString = pVarValue; + + + delete yypvt[-1].mpString; + +} break; + +case YYr38: { /* prop_vector : multi_string */ +#line 662 "policy.y" + + yyval.mpString = new cParseString; + *yyval.mpString = ConcatenateStrings( yypvt[0].mpStringList ); + delete yypvt[0].mpStringList; + +} break; + +case YYr39: { /* attribute_name : string */ +#line 671 "policy.y" + + cDebug d(" parser::string(attribute_name)"); + yyval.mpString = yypvt[0].mpString; + +} break; + +case YYr40: { /* attribute_value : multi_string */ +#line 679 "policy.y" + + yyval.mpString = new cParseString; + cDebug d(" parser::multi_string(attribute_value)"); + *yyval.mpString = ConcatenateStrings( yypvt[0].mpStringList ); + delete yypvt[0].mpStringList; + +} break; + +case YYr41: { /* fco_name : multi_string */ +#line 689 "policy.y" + + cDebug d(" parser::multi_string(fco_name)"); + yyval.mpStringList = yypvt[0].mpStringList; + +} break; + +case YYr42: { /* fco_name : multi_string TWP_PIPE multi_string */ +#line 695 "policy.y" + + + yypvt[-2].mpStringList->push_back( _T("|") ); + MergeIntoList( yypvt[-2].mpStringList, yypvt[0].mpStringList ); + yyval.mpStringList = yypvt[-2].mpStringList; + + delete yypvt[0].mpStringList; + +} break; + +case YYr43: { /* host_name : string */ +#line 710 "policy.y" + + + cDebug d(" parser::multi_string(host_name)"); + yyval.mpString = yypvt[0].mpString; + +} break; + +case YYr44: { /* variable_name : TWP_STRING */ +#line 719 "policy.y" + + cDebug d(" parser::string(variable_name)"); + yyval.mpString = yypvt[0].mpString; + +} break; + +case YYr45: { /* multi_string : multi_string string */ +#line 728 "policy.y" + + yyval.mpStringList->push_back( *yypvt[0].mpString ); + delete yypvt[0].mpString; + +} break; + +case YYr46: { /* multi_string : string */ +#line 733 "policy.y" + + yyval.mpStringList = new cParseStringList; + yyval.mpStringList->push_back( *yypvt[0].mpString ); + delete yypvt[0].mpString; + +} break; + +case YYr47: { /* global_multi_string : global_multi_string global_string */ +#line 742 "policy.y" + + yyval.mpStringList->push_back( *yypvt[0].mpString ); + delete yypvt[0].mpString; + +} break; + +case YYr48: { /* global_multi_string : global_string */ +#line 747 "policy.y" + + yyval.mpStringList = new cParseStringList; + yyval.mpStringList->push_back( *yypvt[0].mpString ); + delete yypvt[0].mpString; + +} break; + +case YYr49: { /* string : TWP_STRING */ +#line 757 "policy.y" + + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", yypvt[0].mpString); + yyval.mpString = yypvt[0].mpString; + +} break; + +case YYr50: { /* string : variable */ +#line 763 "policy.y" + + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", yypvt[0].mpString); + yyval.mpString = yypvt[0].mpString; + +} break; + +case YYr51: { /* global_string : TWP_GLOBAL_STRING */ +#line 772 "policy.y" + + cDebug d(" parser::string(normal)"); + d.TraceNever("--(STRING)--> got string (%s)\n", yypvt[0].mpString); + yyval.mpString = yypvt[0].mpString; + +} break; +#line 343 "..\\..\\mkslexyacc\\etc\\yyparse.cpp" + case YYrACCEPT: + YYACCEPT; + case YYrERROR: + goto yyError; + } +yyNext: + /* + * Look up next state in goto table. + */ + + yyp = &yygo[yypgo[yyi]]; + yyq = yyp++; + yyi = *yyps; + while (yyi < *yyp++) /* busy little loop */ + ; + yystate = yyneg(yyi == *--yyp? yyq[yyq-yyp]: *yyq); +#if YYDEBUG + if (yydebug) + YY_TRACE(yyShowGoto) +#endif + goto yyStack; + +yyerrlabel: ; /* come here from YYERROR */ + yyerrflag = 1; + if (yyi == YYrERROR) { + yyps--, yypv--; +#if YYDEBUG + if (yydebug) yytp--; +#endif + } + +yyError: + switch (yyerrflag) { + + case 0: /* new error */ + yynerrs++; + yyi = yychar; + scan->yyerror("Syntax error"); + if (yyi != yychar) { + /* user has changed the current token */ + /* try again */ + yyerrflag++; /* avoid loops */ + goto yyEncore; + } + + case 1: /* partially recovered */ + case 2: + yyerrflag = 3; /* need 3 valid shifts to recover */ + + /* + * Pop states, looking for a + * shift on `error'. + */ + + for ( ; yyps > stateStack; yyps--, yypv-- +#if YYDEBUG + , yytp-- +#endif + ) { +#ifdef YACC_WINDOWS + if (*yyps >= Sizeof_yypact) /* simple state */ +#else /* YACC_WINDOWS */ + if (*yyps >= (int)sizeof yypact/(int)sizeof yypact[0]) +#endif /* YACC_WINDOWS */ + continue; + yyp = &yyact[yypact[*yyps]]; + yyq = yyp; + do + ; + while (YYERRCODE < *yyp++); + if (YYERRCODE == yyp[-1]) { + yystate = yyneg(yyq[yyq-yyp]); + goto yyStack; + } + + /* no shift in this state */ +#if YYDEBUG + if (yydebug && yyps > stateStack+1) + YY_TRACE(yyShowErrRecovery) +#endif + /* pop stacks; try again */ + } + /* no shift on error - abort */ + break; + + case 3: + /* + * Erroneous token after + * an error - discard it. + */ + + if (yychar == 0) /* but not EOF */ + break; +#if YYDEBUG + if (yydebug) + YY_TRACE(yyShowErrDiscard) +#endif + yyclearin(); + goto yyEncore; /* try again in same state */ + } + YYABORT; + +} +#if YYDEBUG +/* + * Return type of token + */ +int +yy_parse::yyGetType(int tok) +{ + yyNamedType * tp; + for (tp = &yyTokenTypes[yyntoken-1]; tp > yyTokenTypes; tp--) + if (tp->token == tok) + return tp->type; + return 0; +} + + +// Print a token legibly. +char * +yy_parse::yyptok(int tok) +{ + yyNamedType * tp; + for (tp = &yyTokenTypes[yyntoken-1]; tp > yyTokenTypes; tp--) + if (tp->token == tok) + return tp->name; + return ""; +} +/* + * Read state 'num' from YYStatesFile + */ +#ifdef YYTRACE + +char * +yy_parse::yygetState(int num) +{ + int size; + char *cp; + static FILE *yyStatesFile = (FILE *) 0; + static char yyReadBuf[YYMAX_READ+1]; + + if (yyStatesFile == (FILE *) 0 + && (yyStatesFile = fopen(YYStatesFile, "r")) == (FILE *) 0) + return "yyExpandName: cannot open states file"; + + if (num < yynstate - 1) + size = (int)(States[num+1] - States[num]); + else { + /* length of last item is length of file - ptr(last-1) */ + if (fseek(yyStatesFile, 0L, 2) < 0) + goto cannot_seek; + size = (int) (ftell(yyStatesFile) - States[num]); + } + if (size < 0 || size > YYMAX_READ) + return "yyExpandName: bad read size"; + if (fseek(yyStatesFile, States[num], 0) < 0) { + cannot_seek: + return "yyExpandName: cannot seek in states file"; + } + + (void) fread(yyReadBuf, 1, size, yyStatesFile); + yyReadBuf[size] = '\0'; + return yyReadBuf; +} +#endif /* YYTRACE */ +/* + * Expand encoded string into printable representation + * Used to decode yyStates and yyRules strings. + * If the expansion of 's' fits in 'buf', return 1; otherwise, 0. + */ +int +yy_parse::yyExpandName(int num, int isrule, char * buf, int len) +{ + int i, n, cnt, type; + char * endp, * cp, * s; + + if (isrule) + s = yyRules[num].name; + else +#ifdef YYTRACE + s = yygetState(num); +#else + s = "*no states*"; +#endif + + for (endp = buf + len - 8; *s; s++) { + if (buf >= endp) { /* too large: return 0 */ + full: (void) strcpy(buf, " ...\n"); + return 0; + } else if (*s == '%') { /* nonterminal */ + type = 0; + cnt = yynvar; + goto getN; + } else if (*s == '&') { /* terminal */ + type = 1; + cnt = yyntoken; + getN: + if (cnt < 100) + i = 2; + else if (cnt < 1000) + i = 3; + else + i = 4; + for (n = 0; i-- > 0; ) + n = (n * 10) + *++s - '0'; + if (type == 0) { + if (n >= yynvar) + goto too_big; + cp = yysvar[n]; + } else if (n >= yyntoken) { + too_big: + cp = ""; + } else + cp = yyTokenTypes[n].name; + + if ((i = strlen(cp)) + buf > endp) + goto full; + (void) strcpy(buf, cp); + buf += i; + } else + *buf++ = *s; + } + *buf = '\0'; + return 1; +} +#ifndef YYTRACE +/* + * Show current state of yyparse + */ +void +yy_parse::yyShowState() +{ + (void) printf("state %d (%d), char %s (%d)\n%d stateStack entries\n", + yysmap[yystate],yystate,yyptok(yychar),yychar, + yypv - valueStack); +} +// show results of reduction: yyi is rule number +void +yy_parse::yyShowReduce() +{ + (void) printf("Reduce by rule %d (pop#=%d)\n", yyrmap[rule], npop); +} +// show read token +void +yy_parse::yyShowRead() +{ + (void) printf("read %s (%d)\n", yyptok(yychar), yychar); +} +// show Goto +void +yy_parse::yyShowGoto() +{ + (void) printf("goto %d (%d)\n", yysmap[yystate], yystate); +} +// show Shift +void +yy_parse::yyShowShift() +{ + (void) printf("shift %d (%d)\n", yysmap[yystate], yystate); +} +// show error recovery +void +yy_parse::yyShowErrRecovery() +{ + (void) printf("Error recovery pops state %d (%d), uncovers %d (%d)\n", + yysmap[*(yyps-1)], *(yyps-1), yysmap[yystate], yystate); +} +// show token discards in error processing +void +yy_parse::yyShowErrDiscard() +{ + (void) printf("Error recovery discards %s (%d), ", + yyptok(yychar), yychar); +} +#endif /* ! YYTRACE */ +#endif /* YYDEBUG */ + + diff --git a/src/twparser/yyparse.h b/src/twparser/yyparse.h new file mode 100644 index 0000000..efe056d --- /dev/null +++ b/src/twparser/yyparse.h @@ -0,0 +1,234 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +#include "stdtwparser.h" + + + +const int TWP_COMMA = 257; +const int TWP_LPAREN = 258; +const int TWP_RPAREN = 259; +const int TWP_COMMENT = 260; +const int TWP_STRING = 261; +const int TWP_SEMICOLON = 262; +const int TWP_LBRACE = 263; +const int TWP_RBRACE = 264; +const int TWP_DEFAULT = 265; +const int TWP_PIPE = 266; +const int TWP_DOLLAR = 267; +const int TWP_BANG = 268; +const int TWP_PLUS = 269; +const int TWP_MINUS = 270; +const int TWP_DQUOTE = 271; +const int TWP_RARROW = 272; +const int TWP_SECTION = 273; +const int TWP_IFHOST = 274; +const int TWP_ELSE = 275; +const int TWP_ENDIF = 276; +const int TWP_ECHO = 277; +const int TWP_ERROR = 278; +const int TWP_DEFINE = 279; +const int TWP_UNDEF = 280; +const int TWP_CONTENTS = 281; +const int TWP_DBASEVERSION = 282; +const int TWP_ANDAND = 283; +const int TWP_OROR = 284; +const int TWP_BSLASH = 285; +const int TWP_ESCCHAR = 286; +const int TWP_QSTRING = 287; +const int TWP_EQUALS = 288; +const int TWP_GLOBAL_STRING = 289; +typedef union { + class cParseString* mpString; // wrapper around TSTRING + class cParseStringList* mpStringList; + + class cParseRule* mpNode; // representation of FCOSpec + + class cParseSpecMask* mpSpecMask; // representation of specmask + class cParseSpecMaskList* mpSpecMaskList; // ...and a collection + + class cParseNamedAttr* mpAttr; // representation of an attribute + class cParseNamedAttrList* mpAttrList; // ...and a collection +} YYSTYPE; +extern YYSTYPE yylval; + +#ifdef YYTRACE +#define YYDEBUG 1 +#else +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#endif +// C++ YACC parser header +// Copyright 1991 by Mortice Kern Systems Inc. All rights reserved. +// +// yy_parse => class defining a parsing object +// yy_parse needs a class yy_scan, which defines the scanner. +// %prefix or option -p xx determines name of this class; if not used, +// defaults to 'yy_scan' +// +// constructor fills in the tables for this grammar; give it a size +// to determine size of state and value stacks. Default is 150 entries. +// destructor discards those state and value stacks +// +// int yy_parse::yyparse(yy_scan *) invokes parse; if this returns, +// it can be recalled to continue parsing at last point. +// void yy_parse::yyreset() can be called to reset the parse; +// call yyreset() before yy_parse::yyparse(yy_scan *) +#include // uses printf(), et cetera +#include // uses exit() + +const int YYERRCODE = 256; // YACC 'error' value + +// You can use these macros in your action code +#define YYERROR goto yyerrlabel +#define YYACCEPT YYRETURN(0) +#define YYABORT YYRETURN(1) +#define YYRETURN(val) return(val) + +/* + * Simulate bitwise negation as if it was done ona two's complement machine. + * This makes the generated code portable to machines with different + * representations of integers (ie. signed magnitude). + */ +#define yyneg(s) (-((s)+1)) + +#if YYDEBUG +typedef struct yyNamedType_tag { /* Tokens */ + char * name; /* printable name */ + short token; /* token # */ + short type; /* token type */ +} yyNamedType; +typedef struct yyTypedRules_tag { /* Typed rule table */ + char * name; /* compressed rule string */ + short type; /* rule result type */ +} yyTypedRules; +#endif + +#ifdef YACC_WINDOWS + +// include all windows prototypes, macros, constants, etc. + +#include + +// the following is the handle to the current +// instance of a windows program. The user +// program calling yyparse must supply this! + +#ifdef STRICT +extern HINSTANCE hInst; +#else +extern HANDLE hInst; +#endif + +#endif /* YACC_WINDOWS */ + + +class yy_parse { +protected: + +#ifdef YACC_WINDOWS + + // protected member function for actual scanning + + int win_yyparse(yy_scan * ps); // parse with given scanner + +#endif /* YACC_WINDOWS */ + + int mustfree; // set if tables should be deleted + int size; // size of state and value stacks + int reset; // if set, reset state + short yyi; // table index + short yystate; // current state + + short * stateStack; // states stack + YYSTYPE * valueStack; // values stack + short * yyps; // top of state stack + YYSTYPE * yypv; // top of value stack + + YYSTYPE yylval; // saved yylval + YYSTYPE yyval; // $ + YYSTYPE * yypvt; // $n + int yychar; // current token + int yyerrflag; // error flag + int yynerrs; // error count +#if YYDEBUG + int done; // set from trace to stop parse + int rule, npop; // reduction rule # and length + short * typeStack; // type stack to mirror valueStack[] + short * yytp; // top of type stack + char * yygetState(int); // read 'states.out' +#endif +public: +#if YYDEBUG + // C++ has trouble with initialized arrays inside classes + static long * States; // pointer to yyStates[] + static yyTypedRules * Rules; // pointer to yyRules[] + static yyNamedType * TokenTypes; // pointer to yyTokenTypes[] + static int yyntoken; // number of tokens + static int yynvar; // number of variables (nonterminals) + static int yynstate; // number of YACC-generated states + static int yynrule; // number of rules in grammar + + char* yyptok(int); // printable token string + int yyExpandName(int, int, char *, int); + // expand encoded string + virtual int yyGetType(int); // return type of token + virtual void yyShowRead(); // see newly read token + virtual void yyShowState(); // see state, value stacks + virtual void yyShowReduce(); // see reduction + virtual void yyShowGoto(); // see goto + virtual void yyShowShift(); // see shift + virtual void yyShowErrRecovery(); // see error recovery + virtual void yyShowErrDiscard(); // see token discard in error +#endif + yy_scan* scan; // pointer to scanner + int yydebug; // if set, tracing if compiled with YYDEBUG=1 + + yy_parse(int = 150); // constructor for this grammar + yy_parse(int, short *, YYSTYPE *); // another constructor + + ~yy_parse(); // destructor + + int yyparse(yy_scan * ps); // parse with given scanner + + void yyreset() { reset = 1; } // restore state for next yyparse() + + void setdebug(int y) { yydebug = y; } + +// The following are useful in user actions: + + void yyerrok() { yyerrflag = 0; } // clear error + void yyclearin() { yychar = -1; } // clear input + int YYRECOVERING() { return yyerrflag != 0; } +}; +// end of .hpp header + diff --git a/src/twprint/Makefile.am b/src/twprint/Makefile.am new file mode 100644 index 0000000..682a3c0 --- /dev/null +++ b/src/twprint/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 + +INCLUDES = -I.. +LIBS = -ltripwire -lcryptlib @LIBS@ +LDFLAGS = @LDFLAGS@ -L../../lib + +sbin_PROGRAMS = twprint +twprint_SOURCES = \ + stdtwprint.cpp twprint.cpp twprintcmdline.cpp twprinterrors.cpp \ + twprintmain.cpp twprintstrings.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +CLEANFILES = ../../bin/twprint + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin + diff --git a/src/twprint/Makefile.in b/src/twprint/Makefile.in new file mode 100644 index 0000000..2b91e67 --- /dev/null +++ b/src/twprint/Makefile.in @@ -0,0 +1,423 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(twprint_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +sbin_PROGRAMS = twprint$(EXEEXT) +subdir = src/twprint +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(sbin_PROGRAMS) +am_twprint_OBJECTS = stdtwprint.$(OBJEXT) twprint.$(OBJEXT) \ + twprintcmdline.$(OBJEXT) twprinterrors.$(OBJEXT) \ + twprintmain.$(OBJEXT) twprintstrings.$(OBJEXT) +twprint_OBJECTS = $(am_twprint_OBJECTS) +twprint_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(twprint_SOURCES) +DIST_SOURCES = $(twprint_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ -L../../lib +LIBOBJS = @LIBOBJS@ +LIBS = -ltripwire -lcryptlib @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +AM_INSTALL_PROGRAM_FLAGS = -m 755 +INCLUDES = -I.. +twprint_SOURCES = \ + stdtwprint.cpp twprint.cpp twprintcmdline.cpp twprinterrors.cpp \ + twprintmain.cpp twprintstrings.cpp + +CLEANFILES = ../../bin/twprint +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/twprint/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/twprint/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$f"; \ + done + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +twprint$(EXEEXT): $(twprint_OBJECTS) $(twprint_DEPENDENCIES) + @rm -f twprint$(EXEEXT) + $(CXXLINK) $(twprint_LDFLAGS) $(twprint_OBJECTS) $(twprint_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-sbinPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am uninstall-sbinPROGRAMS + + +all: $(sbin_PROGRAMS) + @test -d ../../bin && ln -f $(sbin_PROGRAMS) ../../bin +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/twprint/resource.h b/src/twprint/resource.h new file mode 100644 index 0000000..8fc8ab8 --- /dev/null +++ b/src/twprint/resource.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script3.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + diff --git a/src/twprint/stdtwprint.cpp b/src/twprint/stdtwprint.cpp new file mode 100644 index 0000000..6894eb9 --- /dev/null +++ b/src/twprint/stdtwprint.cpp @@ -0,0 +1,40 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdtwprint.cpp +// Date....: 5/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwprint.h" + +// eof: stdtwprint.cpp diff --git a/src/twprint/stdtwprint.h b/src/twprint/stdtwprint.h new file mode 100644 index 0000000..141f9c1 --- /dev/null +++ b/src/twprint/stdtwprint.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdtwprint.h +// +// Standard includes for twprint +// + +#include "core/stdcore.h" + diff --git a/src/twprint/twprint.cpp b/src/twprint/twprint.cpp new file mode 100644 index 0000000..08047e6 --- /dev/null +++ b/src/twprint/twprint.cpp @@ -0,0 +1,72 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twprint.cpp +// Date....: 05/11/99 +// Creator.: bmcfeely +// +// + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Includes +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "stdtwprint.h" +#include "twprint.h" +#include "tw/tw.h" // for cTW +#include "twprinterrors.h" +#include "core/errortable.h" + +TSS_ImplementPackage( cTWPrint ) + +//============================================================================= +// cTWPrint::cTWPrint() +//----------------------------------------------------------------------------- +// REQUIRES: +// +// EFFECTS: +// +// POSTCONDITIONS: +// +// COMPLEXITY: +// Constant +// +cTWPrint::cTWPrint() +{ + // + // set up dependencies + // + TSS_Dependency( cTW ); + TSS_REGISTER_PKG_ERRORS ( twprint ); +} + +// eof: twprint.cpp diff --git a/src/twprint/twprint.h b/src/twprint/twprint.h new file mode 100644 index 0000000..c775375 --- /dev/null +++ b/src/twprint/twprint.h @@ -0,0 +1,59 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twprint.h +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// +// The Package class for the TSS twprint executable. +// + +#ifndef __TWPRINT_H +#define __TWPRINT_H + +//--Requirements + +#include "core/package.h" // for: Packaging Abstraction + +//--Classes + +TSS_BeginPackage( cTWPrint ) + + TSS_DECLARE_STRINGTABLE; + + public: + cTWPrint(); + +TSS_EndPackage( cTWPrint ) + +#endif //#ifndef __TWPRINT_H + diff --git a/src/twprint/twprintcmdline.cpp b/src/twprint/twprintcmdline.cpp new file mode 100644 index 0000000..459703e --- /dev/null +++ b/src/twprint/twprintcmdline.cpp @@ -0,0 +1,972 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twprintcmdline.cpp +// +#include "stdtwprint.h" +#include "twprintcmdline.h" +#include "twprintstrings.h" // strings specific to twprint +#include "twprintcmdline.h" // functions for the cmd line +#include "twprinterrors.h" + +#include "core/cmdlineparser.h" +#include "core/errorgeneral.h" +#include "core/errorbucketimpl.h" // for the error table +#include "core/usernotify.h" // for notifying the user of even +#include "core/serializerimpl.h" // cSerializerImpl +#include "core/archive.h" // cArchive and friends + +#include "tw/configfile.h" +#include "tw/fcodatabasefile.h" // cFCODatabaseFile +#include "tw/fcoreport.h" // for reports +#include "tw/textdbviewer.h" +#include "tw/textreportviewer.h" // text report viewer +#include "tw/twutil.h" +#include "tw/headerinfo.h" +#include "tw/systeminfo.h" +#include "tw/twerrors.h" +#include "tw/dbdatasource.h" +#include "tw/twstrings.h" + +#include "twcrypto/keyfile.h" // cKeyFile -- used for encryption + +#include "util/fileutil.h" + +#include "fco/fcogenre.h" +#include "fco/genreswitcher.h" +#include "fco/twfactory.h" +#include "fco/fcospeclist.h" // cFCOSpecList +#include "fco/fcopropdisplayer.h" +#include + +/////////////////////////////////////////////////////////////////////////////// +// Static functions -- +/////////////////////////////////////////////////////////////////////////////// +static void InitCmdLineCommon(cCmdLineParser& parser); + // A method for initializing the command line parser with arguments that + // are common to all modes of twprint. + +//############################################################################# +// cTWPrintCmdLine +//############################################################################# + + +// this is used to make required condition checking in the Init() functions a little more compact +#define TEST_INIT_REQUIREMENT(t, n)\ + if(! t)\ + {\ + TCERR << TSS_GetString(cTW, n) << std::endl;\ + return false;\ + } + +// TODO: get Matt to update this with changes he made to tripwire + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineCommon -- +// Initialize the cmdlineparser with the arguments that are common +// to all modes. Other parameters must be added in the +// InitCmdLineParser method of the derived mode. +/////////////////////////////////////////////////////////////////////////////// +static void InitCmdLineCommon(cCmdLineParser& parser) +{ + // help + parser.AddArg(cTWPrintCmdLine::HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_NONE); + + // mode + parser.AddArg(cTWPrintCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWPrintCmdLine::MODE_DBPRINT, TSTRING(_T("")), TSTRING(_T("print-dbfile")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWPrintCmdLine::MODE_REPORTPRINT,TSTRING(_T("")), TSTRING(_T("print-report")), cCmdLineParser::PARAM_NONE); + + // reporting + parser.AddArg(cTWPrintCmdLine::VERBOSE, TSTRING(_T("v")), TSTRING(_T("verbose")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWPrintCmdLine::SILENT, TSTRING(_T("s")), TSTRING(_T("silent")), cCmdLineParser::PARAM_NONE); + parser.AddArg(cTWPrintCmdLine::SILENT, TSTRING(_T("")), TSTRING(_T("quiet")), cCmdLineParser::PARAM_NONE); + + // config file overrides + parser.AddArg(cTWPrintCmdLine::CFG_FILE, TSTRING(_T("c")), TSTRING(_T("cfgfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWPrintCmdLine::LOCAL_KEY_FILE, TSTRING(_T("L")), TSTRING(_T("local-keyfile")), cCmdLineParser::PARAM_ONE); + parser.AddArg(cTWPrintCmdLine::SITE_KEY_FILE, TSTRING(_T("S")), TSTRING(_T("site-keyfile")), cCmdLineParser::PARAM_ONE); + + // unattended operation + parser.AddArg(cTWPrintCmdLine::PASSPHRASE, TSTRING(_T("P")), TSTRING(_T("passphrase")), cCmdLineParser::PARAM_ONE); + + // the paramters to the command line ... for now, this will take "many", even though in some + // modes, this is not valid to do... + + // NOTE -- print report doesn't take any naked parameters, and neither does print database (we took that + // functionality out) so I changed this to PARAM_NONE. + + // NOTE -- We __DO__ take "naked" parameters in print-database mode, contrary to the above comment!!! It is an error + // to add this argument here, in the "common" code between the two modes of twprint. I'm moving the PARAMS arg to + // twprint --print-database's "personal" initialization (below). -DRA 8/9/99 + + //parser.AddArg(cTWPrintCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::/*PARAM_NONE*/PARAM_MANY); + // Error for print-report!!!! + + parser.AddMutEx(cTWPrintCmdLine::VERBOSE, cTWPrintCmdLine::SILENT); +} + +/////////////////////////////////////////////////////////////////////////////// +// GetMode -- processes the command line arguments and creates an appropriate +// structure for the selected mode, or NULL if an error occurs +/////////////////////////////////////////////////////////////////////////////// +iTWMode* cTWPrintCmdLine::GetMode( int argc, const TCHAR* const * argv ) +{ + // note -- it is assumed the executable name is the first parameter + if(argc < 2) + { + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + + int mode = MODE; + const TCHAR* pcMode; + if(_tcscmp(argv[1], _T("-m")) == 0) + { + if(argc < 3) + { + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_ERR_NO_MODE) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + pcMode = argv[2]; + if (_tcscmp(argv[2], _T("d")) == 0) + mode = MODE_DBPRINT; + else if (_tcscmp(argv[2], _T("r")) == 0) + mode = MODE_REPORTPRINT; + } + else + { + pcMode = argv[1]; + if (_tcscmp(argv[1], _T("--print-dbfile")) == 0) + mode = MODE_DBPRINT; + else if (_tcscmp(argv[1], _T("--print-report")) == 0) + mode = MODE_REPORTPRINT; + else if (_tcscmp(argv[1], _T("--version")) == 0) + { + TCOUT << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + return NULL; + } + else if (_tcscmp(argv[1], _T("--help")) == 0 || _tcscmp(argv[1], _T("-?")) == 0) + mode = MODE_HELP; + } + + if(mode == MODE) + { + // unknown mode switch + cDebug d("cTWPrintCmdLine::GetMode"); + d.TraceError(_T("Error: Bad mode switch: %s\n"), pcMode); + TCERR << TSS_GetString(cTW, tw::STR_UNKOWN_MODE_SPECIFIED) << pcMode << std::endl; + TCERR << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + return NULL; + } + + + iTWMode* pRtn = 0; + switch(mode) + { + case cTWPrintCmdLine::MODE_DBPRINT: + pRtn = new cTWPrintDBMode; + break; + case cTWPrintCmdLine::MODE_REPORTPRINT: + pRtn = new cTWPrintReportMode; + break; + case cTWPrintCmdLine::MODE_HELP: + pRtn = new cTWPrintHelpMode; + break; + default: + ASSERT(false); + } + + return pRtn; +} + +//############################################################################# +// cTWPrintModeCommon -- contains data common to all modes; all cTWMode*_i will +// derive from this class. +//############################################################################# +class cTWPrintModeCommon +{ +public: + int mVerbosity; // must be 0 <= n <= 2 + std::string mPassPhrase; // pass phrase for private key + TSTRING mLocalKeyFile; + TSTRING mSiteKeyFile; + TSTRING mConfigFilePath; + + cTWPrintModeCommon() : mVerbosity(1) {} + cTextReportViewer::ReportingLevel mReportLevel; // The level of reporting to use. +}; + +/////////////////////////////////////////////////////////////////////////////// +// FillOutCommonConfigInfo -- fills out all the common info with config file information +/////////////////////////////////////////////////////////////////////////////// +static void FillOutCommonConfigInfo(cTWPrintModeCommon* pModeInfo, const cConfigFile& cf) +{ + TSTRING str; + if(cf.Lookup(TSTRING(_T("LOCALKEYFILE")), str)) + pModeInfo->mLocalKeyFile = str; + + if(cf.Lookup(TSTRING(_T("SITEKEYFILE")), str)) + pModeInfo->mSiteKeyFile = str; + + // + // turn all of the file names into full paths (they're relative to the exe dir) + // + TSTRING fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mLocalKeyFile, cSystemInfo::GetExeDir() )) + pModeInfo->mLocalKeyFile = fullPath; +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutCmdLineInfo -- fills out info common to all modes that appears on the +// command line. +/////////////////////////////////////////////////////////////////////////////// +static void FillOutCmdLineInfo(cTWPrintModeCommon* pModeInfo, const cCmdLineParser& cmdLine) +{ + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWPrintCmdLine::VERBOSE: + pModeInfo->mVerbosity = 2; + break; + case cTWPrintCmdLine::SILENT: + pModeInfo->mVerbosity = 0; + break; + case cTWPrintCmdLine::LOCAL_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mLocalKeyFile = iter.ParamAt(0); + break; + case cTWPrintCmdLine::SITE_KEY_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + pModeInfo->mSiteKeyFile = iter.ParamAt(0); + break; + case cTWPrintCmdLine::PASSPHRASE: + { + // this bites! I have to make sure it is a narrow char string + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser +#ifdef _UNICODE + char* buf = new char[2*(wcslen(iter.ParamAt(0).c_str()) + 1)]; + wcstombs(buf, iter.ParamAt(0).c_str(), sizeof(buf)); + pModeInfo->mPassPhrase = buf; + delete [] buf; +#else + pModeInfo->mPassPhrase = iter.ParamAt(0); +#endif + } + break; + case cTWPrintCmdLine::REPORTLEVEL: + { + if ( iter.ParamAt(0) == _T("0")) + pModeInfo->mReportLevel = cTextReportViewer::SINGLE_LINE; + else if( iter.ParamAt(0) == _T("1") ) + pModeInfo->mReportLevel = cTextReportViewer::PARSEABLE; + else if( iter.ParamAt(0) == _T("2") ) + pModeInfo->mReportLevel = cTextReportViewer::SUMMARY_ONLY; + else if( iter.ParamAt(0) == _T("3") ) + pModeInfo->mReportLevel = cTextReportViewer::CONCISE_REPORT; + else if( iter.ParamAt(0) == _T("4") ) + pModeInfo->mReportLevel = cTextReportViewer::FULL_REPORT; + else + { + // They specified an illegal level, error. + TSTRING errStr = _T("Invalid Level: "); + errStr += iter.ParamAt(0); + throw eTWPrintInvalidReportLevel( errStr ); + } + } + //done with report-level stuff. + break; + default: + break; + } + } + + // use the verbosity information + ASSERT((pModeInfo->mVerbosity >= 0) && (pModeInfo->mVerbosity < 3)); + iUserNotify::GetInstance()->SetVerboseLevel(pModeInfo->mVerbosity); +} + +//############################################################################# +// cTWPrintReportMode +//############################################################################# +class cTWPrintReportMode_i : public cTWPrintModeCommon +{ +public: + TSTRING mReportFile; + + // ctor can set up some default values + cTWPrintReportMode_i() : cTWPrintModeCommon(){} +}; + +void cTWPrintReportMode::SetConfigFile( TSTRING configFilePath ) +{ + mpData->mConfigFilePath = configFilePath; +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutReportModeConfigInfo -- fills out all the common info with config file information +/////////////////////////////////////////////////////////////////////////////// +void cTWPrintReportMode::FillOutReportModeConfigInfo(cTWPrintReportMode_i* pModeInfo, const cConfigFile& cf) +{ + TSTRING str; + if(cf.Lookup(TSTRING(_T("REPORTFILE")), str)) + pModeInfo->mReportFile = str; + + // Find out what level of reporting we should use, use default level if none + // has been specified. + if(cf.Lookup(TSTRING(_T("REPORTLEVEL")), str)) + { + if (_tcsicmp(str.c_str(), _T("0")) == 0) + /*throw eTWPrintReportLevelZeroCfg( TSS_GetString( cTWPrint, twprint::STR_ERR2_REPORT_LEVEL_ZERO_CFG ) ); + // We error if reporting-level 0 is specified in the config. file + // Level zero must be specified on the command line. - changed, 7/14/99 dra */ + pModeInfo->mReportLevel = cTextReportViewer::SINGLE_LINE; + else if (_tcsicmp(str.c_str(), _T("1")) == 0) + pModeInfo->mReportLevel = cTextReportViewer::PARSEABLE; + else if (_tcsicmp(str.c_str(), _T("2")) == 0) + pModeInfo->mReportLevel = cTextReportViewer::SUMMARY_ONLY; + else if (_tcsicmp(str.c_str(), _T("3")) == 0) + pModeInfo->mReportLevel = cTextReportViewer::CONCISE_REPORT; + else if (_tcsicmp(str.c_str(), _T("4")) == 0) + pModeInfo->mReportLevel = cTextReportViewer::FULL_REPORT; + else + { + // They specified an illegal level, error. + TSTRING errStr = _T("Invalid Level: "); + errStr += str; + throw eTWPrintInvalidReportLevelCfg( errStr ); + } + } + else + // Use the default level of reporting, they specified none in configuration file. + pModeInfo->mReportLevel = cTextReportViewer::CONCISE_REPORT; + + // + // turn all of the file names into full paths (they're relative to the exe dir) + // + TSTRING fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mReportFile, cSystemInfo::GetExeDir() )) + pModeInfo->mReportFile = fullPath; +} + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWPrintReportMode::cTWPrintReportMode() +{ + mpData = new cTWPrintReportMode_i; +} + +cTWPrintReportMode::~cTWPrintReportMode() +{ + delete mpData; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWPrintReportMode::InitCmdLineParser(cCmdLineParser& parser) +{ + InitCmdLineCommon( parser ); + + parser.AddArg(cTWPrintCmdLine::REPORT_FILE, TSTRING(_T("r")), TSTRING(_T("twrfile")), cCmdLineParser::PARAM_ONE); + + // multiple levels of reporting + parser.AddArg(cTWPrintCmdLine::REPORTLEVEL, TSTRING(_T("t")), TSTRING(_T("report-level")), cCmdLineParser::PARAM_ONE); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWPrintReportMode::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutCommonConfigInfo(mpData, cf); + FillOutReportModeConfigInfo(mpData, cf); + + // TODO -- should I error or warn for (1) mutual exclustion errors or (2) unneeded cmd line + // parameters? I think I should, but I won't right now. + // TODO -- error at the end of Init() if I am missing any requires parameter values.. + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + // now do the stuff specific to this mode... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWPrintCmdLine::REPORT_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mpData->mReportFile = iter.ParamAt(0); + break; + case cTWPrintCmdLine::REPORTLEVEL: + { + if ( iter.ParamAt(0) == _T("0")) + mpData->mReportLevel = cTextReportViewer::SINGLE_LINE; + else if( iter.ParamAt(0) == _T("1") ) + mpData->mReportLevel = cTextReportViewer::PARSEABLE; + else if( iter.ParamAt(0) == _T("2") ) + mpData->mReportLevel = cTextReportViewer::SUMMARY_ONLY; + else if( iter.ParamAt(0) == _T("3") ) + mpData->mReportLevel = cTextReportViewer::CONCISE_REPORT; + else if( iter.ParamAt(0) == _T("4") ) + mpData->mReportLevel = cTextReportViewer::FULL_REPORT; + else + { + // They specified an illegal level, error. + TSTRING errStr = _T("Invalid Level: "); + errStr += iter.ParamAt(0); + throw eTWPrintInvalidReportLevel( errStr ); + } + } + //done with report-level stuff. + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * report file + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mReportFile.empty()), tw::STR_ERR_MISSING_REPORT); + + // check that the config file and site key file are in sync... + // + if( ! mpData->mConfigFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mpData->mConfigFilePath, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWPrintReportMode::Execute(cErrorQueue* pQueue) +{ + cFCOReport report; + cFCOReportHeader reportHeader; + + try + { + ASSERT( ! mpData->mReportFile.empty() ); + // make sure the report file exists... + cFileUtil::TestFileExists(mpData->mReportFile); + + cKeyFile localKeyfile; + const cElGamalSigPublicKey* pKey; + cFCOReport report; + + cTWUtil::OpenKeyFile( localKeyfile, mpData->mLocalKeyFile ); + pKey = localKeyfile.GetPublicKey(); + + if( !cTWUtil::IsObjectEncrypted( mpData->mReportFile.c_str(), cFCOReport::GetFileHeaderID(), TSS_GetString( cTW, tw::STR_ERR_REPORT_READ ) ) ) + { + // note (rather than warn) if the database is not encrytped + iUserNotify::GetInstance()->Notify(iUserNotify::V_NORMAL, TSS_GetString(cTW, tw::STR_REPORT_NOT_ENCRYPTED).c_str()); + } + + // open the report... + bool bDummy; + cTWUtil::ReadReport( mpData->mReportFile.c_str(), reportHeader, report, pKey, false, bDummy ); + + // print it + cTextReportViewer trv( reportHeader, report ); + trv.PrintTextReport( _T("-"), mpData->mReportLevel ); + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + return 1; + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage -- returns a mode-specific usage statement. +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWPrintReportMode::GetModeUsage() +{ + return TSS_GetString(cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_REPORT ); +} + +//############################################################################# +// cTWPrintDBMode +//############################################################################# +class cTWPrintDBMode_i : public cTWPrintModeCommon +{ +public: + TSTRING mDbFile; + std::vector mFilesToCheck; + + // ctor can set up some default values + cTWPrintDBMode_i() : cTWPrintModeCommon() {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWPrintDBMode::cTWPrintDBMode() +{ + mpData = new cTWPrintDBMode_i; +} + +cTWPrintDBMode::~cTWPrintDBMode() +{ + delete mpData; +} + +void cTWPrintDBMode::SetConfigFile( TSTRING configFilePath ) +{ + mpData->mConfigFilePath = configFilePath; +} + +/////////////////////////////////////////////////////////////////////////////// +// FillOutDBModeConfigInfo -- fills out all the common info with config file information +/////////////////////////////////////////////////////////////////////////////// +void cTWPrintDBMode::FillOutDBModeConfigInfo(cTWPrintDBMode_i* pModeInfo, const cConfigFile& cf) +{ + TSTRING str; + if(cf.Lookup(TSTRING(_T("DBFILE")), str)) + pModeInfo->mDbFile = str; + + // + // turn all of the file names into full paths (they're relative to the exe dir) + // + TSTRING fullPath; + if(iFSServices::GetInstance()->FullPath( fullPath, pModeInfo->mDbFile, cSystemInfo::GetExeDir() )) + pModeInfo->mDbFile = fullPath; +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWPrintDBMode::InitCmdLineParser( cCmdLineParser& parser ) +{ + InitCmdLineCommon( parser ); + + parser.AddArg(cTWPrintCmdLine::DB_FILE, TSTRING(_T("d")), TSTRING(_T("dbfile")), cCmdLineParser::PARAM_ONE); + + // For the variable object list. + parser.AddArg(cTWPrintCmdLine::PARAMS, TSTRING(_T("")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWPrintDBMode::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + // first, fill out everything with the config file info... + FillOutCommonConfigInfo(mpData, cf); + FillOutDBModeConfigInfo(mpData, cf); + + // TODO -- should I error or warn for (1) mutual exclustion errors or (2) unneeded cmd line + // parameters? I think I should, but I won't right now. + // TODO -- error at the end of Init() if I am missing any requires parameter values.. + + // now, parse the command line... + // this takes care of the common stuff... + FillOutCmdLineInfo(mpData, cmdLine); + + // now do the stuff specific to this mode... + cCmdLineIter iter(cmdLine); + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWPrintCmdLine::DB_FILE: + ASSERT(iter.NumParams() > 0); // should be caught by cmd line parser + mpData->mDbFile = iter.ParamAt(0); + break; + case cTWPrintCmdLine::PARAMS: + { + // pack all of these onto the files to check list... + mpData->mFilesToCheck.clear(); + for(int i=0; i < iter.NumParams(); i++) + { + mpData->mFilesToCheck.push_back(iter.ParamAt(i)); + } + } + default: + // TODO: should I do anything, or just ignore this? + ; + } + } + + //---------------------------------------- + // I require the following information: + // + // * local key file + // * report file + //----------------------------------------- + TEST_INIT_REQUIREMENT((! mpData->mLocalKeyFile.empty()), tw::STR_ERR_MISSING_LOCAL_KEY); + TEST_INIT_REQUIREMENT((! mpData->mDbFile.empty()), tw::STR_ERR_MISSING_DB); + + // check that the config file and site key file are in sync... + // + if( ! mpData->mConfigFilePath.empty() ) + try + { + if (cTWUtil::VerifyCfgSiteKey( mpData->mConfigFilePath, mpData->mSiteKeyFile ) == false) + cTWUtil::PrintErrorMsg(eTWCfgUnencrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + catch (eTWUtilCfgKeyMismatch& e) + { + e.SetFatality(false); + cTWUtil::PrintErrorMsg(e); + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWPrintDBMode::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWPrintDBMode::Execute"); + int ret = 0; + + try + { + ASSERT( ! mpData->mDbFile.empty() ); + // make sure the database file exists... + cFileUtil::TestFileExists(mpData->mDbFile); + + cFCODatabaseFile db; + cKeyFile localKeyfile; + const cElGamalSigPublicKey* pKey = 0; + + cTWUtil::OpenKeyFile(localKeyfile, mpData->mLocalKeyFile); + pKey = localKeyfile.GetPublicKey(); + + if( !cTWUtil::IsObjectEncrypted( mpData->mDbFile.c_str(), cFCODatabaseFile::GetFileHeaderID(), TSS_GetString( cTW, tw::STR_ERR_DB_READ ) ) ) + { + // warn if the database is not encrytped + if(iUserNotify::GetInstance()->GetVerboseLevel() > iUserNotify::V_SILENT) + { + cTWUtil::PrintErrorMsg(eTWDbNotEncrypted(_T(""), eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + } + + // open the database; note that ReadDatabase will set bEncrypted and open the + // key file if necessary + bool bDummy; + cTWUtil::ReadDatabase(mpData->mDbFile.c_str(), db, pKey, bDummy); + + if( mpData->mFilesToCheck.size() > 0 ) + { + //------------------------------------------------ + // print specific FCOs from the database + //------------------------------------------------ + cTWUtil::GenreObjList listOut; + cTWUtil::ParseObjectList( listOut, mpData->mFilesToCheck ); + + // now, iterate through the list of objects... + // + cFCODatabaseFile::iterator dbIter( db ); + for( cTWUtil::GenreObjList::iterator genreIter = listOut.begin(); genreIter != listOut.end(); genreIter++ ) + { + dbIter.SeekToGenre( genreIter->first ); + if( ! dbIter.Done() ) + { + cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre)dbIter.GetGenre() ); + cDbDataSourceIter dsIter( &dbIter.GetDb() ); + dsIter.SetErrorBucket(pQueue); + iFCONameTranslator* pNT = cGenreSwitcher::GetInstance()->GetFactoryForGenre( (cGenre::Genre)dbIter.GetGenre() )->GetNameTranslator(); + // + // iterate over all the objects in this genre.... + // + for(cTWUtil::ObjList::iterator it = genreIter->second.begin(); it != genreIter->second.end(); it++) + { + try + { + cFCOName name = cTWUtil::ParseObjectName( *it ); + dsIter.SeekToFCO( name, false ); + if( (! dsIter.Done()) && (dsIter.HasFCOData()) ) + { + cTextDBViewer::OutputFCO( dsIter, dbIter.GetGenreHeader().GetPropDisplayer(), pNT, &TCOUT ); + } + else + { + eTWUtilObjNotInDb e( *it ); + e.SetFatality( false ); + cTWUtil::PrintErrorMsg( e ); + } + } + catch( eError& e) + { + e.SetFatality( false ); + cTWUtil::PrintErrorMsg( e ); + } + } + + } + else + { + eTWDbDoesntHaveGenre e( cGenreSwitcher::GetInstance()->GenreToString( (cGenre::Genre)genreIter->first, true ) ); + e.SetFatality( false ); + cTWUtil::PrintErrorMsg( e ); + } + } + + } + else + { + //------------------------------------------------ + // printing the entire db + //------------------------------------------------ + cTextDBViewer::PrintDB( db, _T("-") ); + } + + } + catch(eError& e) + { + cTWUtil::PrintErrorMsg(e); + return 1; + } + + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetModeUsage -- returns a mode-specific usage statement. +/////////////////////////////////////////////////////////////////////////////// +TSTRING cTWPrintDBMode::GetModeUsage() +{ + return TSS_GetString(cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_DATABASE ); +} + + + +//############################################################################# +// cTWPrintHelpMode +//############################################################################# + +class cTWPrintHelpMode_i +{ +public: + cTWPrintHelpMode_i() {} + ~cTWPrintHelpMode_i() {} + + // A list of modes to output usage statements for: + std::set< TSTRING > mlModes; + std::set< TSTRING > mPrinted; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// ctor, dtor +/////////////////////////////////////////////////////////////////////////////// +cTWPrintHelpMode::cTWPrintHelpMode() +{ + mpData = new cTWPrintHelpMode_i(); +} + +cTWPrintHelpMode::~cTWPrintHelpMode() +{ + delete mpData; +} + +void cTWPrintHelpMode::SetConfigFile( TSTRING configFilePath ) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// InitCmdLineParser +/////////////////////////////////////////////////////////////////////////////// +void cTWPrintHelpMode::InitCmdLineParser(cCmdLineParser& cmdLine) +{ + // We're only interested in one parameter, that being help. Anything else + // passed to this mode should be a cmdlineparser error. + cmdLine.AddArg(cTWPrintCmdLine::MODE, TSTRING(_T("m")), TSTRING(_T("")), cCmdLineParser::PARAM_MANY, true); + cmdLine.AddArg(cTWPrintCmdLine::MODE_HELP, TSTRING(_T("?")), TSTRING(_T("help")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWPrintCmdLine::MODE_HELP_ALL, TSTRING(_T("")), TSTRING(_T("all")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWPrintCmdLine::MODE_REPORTPRINT, TSTRING(_T("r")), TSTRING(_T("print-report")), cCmdLineParser::PARAM_MANY); + cmdLine.AddArg(cTWPrintCmdLine::MODE_DBPRINT, TSTRING(_T("d")), TSTRING(_T("print-dbfile")), cCmdLineParser::PARAM_MANY); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +bool cTWPrintHelpMode::Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) +{ + cCmdLineIter iter(cmdLine); + + // Grab the arguments from the help parameter: + for(iter.SeekBegin(); ! iter.Done(); iter.Next()) + { + switch(iter.ArgId()) + { + case cTWPrintCmdLine::MODE_HELP: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + mpData->mlModes.insert( iter.ParamAt(i) ); + } + break; + case cTWPrintCmdLine::MODE: + { + int i; + for( i = 0; i < iter.NumParams(); ++i ) + { + mpData->mlModes.insert( iter.ParamAt(i) ); + } + } + break; + // Begin ugly hack so we can allow users to enter the mode + // names with "--" prepended. We have to do this, since + // the cmdlineparser treats them as switches. + case cTWPrintCmdLine::MODE_HELP_ALL: // fall through + case cTWPrintCmdLine::MODE_REPORTPRINT: // fall through + case cTWPrintCmdLine::MODE_DBPRINT: + { + int i; + TSTRING str = iter.ActualParam(); + // Kill off the initial "--" or "-" + str.erase( 0, 1 ); + if( str.length() != 1) + str.erase( 0, 1 ); + + // push back the parameter that was actually passed. + mpData->mlModes.insert( str ); + // grab all the "parameters" following the mode/switch, since + // they may be valid modes without the "--" prepended. + for( i = 0; i < iter.NumParams(); ++i ) + mpData->mlModes.insert( iter.ParamAt(i) ); + } + break; + default: + // should I do anything, or just ignore this? + ; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Execute +/////////////////////////////////////////////////////////////////////////////// +int cTWPrintHelpMode::Execute(cErrorQueue* pQueue) +{ + cDebug d("cTWPrintHelpMode::Execute"); + + // The iterator we will use to traverse the list of arguments: + std::set< TSTRING >::iterator it = mpData->mlModes.begin(); + + // We'll want to output the version information, regardless: + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_VERSION) << std::endl; + TCOUT << TSS_GetString( cTW, tw::STR_VERSION) << std::endl; + + if( it == mpData->mlModes.end() ) // all that was passed was --help + { + // Output a short usage statement for each mode + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_USAGE_SUMMARY); + // + // That's it. return + return 1; + } + + for( ; it != mpData->mlModes.end(); ++it ) + { + if( _tcscmp( (*it).c_str(), _T("all")) == 0 ) + { + //Since --help all was passed, emit all help messages and return. + TCOUT<< TSS_GetString( cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_REPORT ); + TCOUT<< TSS_GetString( cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_DATABASE ); + + //We're done, return + return 1; + } + } + + //We need some subset of the usage statements. Figure out which modes have + //been specified: + it = mpData->mlModes.begin(); + for( ; it != mpData->mlModes.end(); ++it ) + { + if ( _tcscmp( (*it).c_str(), _T("print-report") ) == 0 || _tcscmp( (*it).c_str(), _T("r") ) == 0) + { + // make sure we don't print the same help twice... + if( mpData->mPrinted.find(_T("print-report")) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_REPORT ); + mpData->mPrinted.insert( _T("print-report") ); + } + } + else if( _tcscmp( (*it).c_str(), _T("print-dbfile") ) == 0 || _tcscmp( (*it).c_str(), _T("d") ) == 0) + { + if( mpData->mPrinted.find(_T("print-dbfile")) == mpData->mPrinted.end() ) + { + TCOUT<< TSS_GetString( cTWPrint, twprint::STR_TWPRINT_HELP_PRINT_DATABASE ); + mpData->mPrinted.insert( _T("print-dbfile") ); + } + } + else + { + cTWUtil::PrintErrorMsg( eTWPrintInvalidParamHelp( (*it), eError::NON_FATAL ) ); + TCOUT << std::endl; + // emit error/warning string, this mode does not exist + } + } + + //Everything went okay + return 1; +} + diff --git a/src/twprint/twprintcmdline.h b/src/twprint/twprintcmdline.h new file mode 100644 index 0000000..89190c1 --- /dev/null +++ b/src/twprint/twprintcmdline.h @@ -0,0 +1,193 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twprintcmdline.h +// +// cTWPrintCmdLine -- holds all information on twprint's command line +// iTWMode -- abstract base class for a mode of operation in tripwire +#ifndef __TWPRINTCMDLINE_H +#define __TWPRINTCMDLINE_H + +#ifndef __TCHAR_H +#include "tchar.h" +#endif + +class cConfigFile; +class cCmdLineParser; +class cErrorQueue; +class cErrorBucket; +class iTWMode; + +TSS_EXCEPTION( eTWPrintInvalidParamHelp, eError ) +TSS_EXCEPTION( eTWPrintInvalidReportLevel, eError ) +TSS_EXCEPTION( eTWPrintInvalidReportLevelCfg, eError ) + +// Help is requested for a non-existent mode. + +/////////////////////////////////////////////////////////////////////////////// +// cTWPrintCmdLine -- class with a bunch of static member functions helpful in parsing +// the tripwire command line +/////////////////////////////////////////////////////////////////////////////// +class cTWPrintCmdLine +{ +public: + static iTWMode* GetMode(int argc, const TCHAR* const* argv); + // after the command line has been read, call this to extract the mode information + // from the command line, create an iTWMode-derived class, and return it. If this + // fails, it will print the error message to stderr and return NULL. + + // constants for all the command line arguments + enum CmdLineArgs + { + HELP, + + // modes + MODE, // generic -m + MODE_DBPRINT, + MODE_REPORTPRINT, + MODE_HELP, + MODE_HELP_ALL, + + VERBOSE, + SILENT, + + CFG_FILE, + LOCAL_KEY_FILE, + SITE_KEY_FILE, + + DB_FILE, + REPORT_FILE, + + PASSPHRASE, + REPORTLEVEL, + + PARAMS, // the final parameters + + NUM_CMDLINEARGS + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// iTWMode -- base class that contains an interface for initializing tripwire +// in a mode of operation and executing in that mode; a class is derived +// from this for each mode of operation +/////////////////////////////////////////////////////////////////////////////// +class iTWMode +{ +public: + + virtual void InitCmdLineParser(cCmdLineParser& parser) = 0; + // call this to initialize the command line parser. All modes must override this + // method. A static function will be made to initialize the cmdline with parameters + // common to all modes. + virtual bool Init(const cConfigFile& cf, const cCmdLineParser& cmdLine) = 0; + // call this to ask the mode object to initialize all of its data structures + // with the passed in information. If it returns false, it can be assumed that an error + // message was spit to stderr. + virtual int Execute(cErrorQueue* pQueue) = 0; + // go to work! TODO -- I don't know how errors (or return values) should be conveyed + // I think that maybe this guy should return an int indicating the return value + virtual TSTRING GetModeUsage( void ) = 0; + // Returns a TSTRING that describes specific usage for a derived mode. + virtual cTWPrintCmdLine::CmdLineArgs GetModeID() = 0; + virtual void SetConfigFile( TSTRING configFilePath ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Report Printing +/////////////////////////////////////////////////////////////////////////////// +class cTWPrintReportMode_i; +class cTWPrintReportMode : public iTWMode +{ +public: + cTWPrintReportMode(); + virtual ~cTWPrintReportMode(); + + + void FillOutReportModeConfigInfo(cTWPrintReportMode_i* pModeInfo, const cConfigFile& cf); + + virtual void InitCmdLineParser( cCmdLineParser& parser); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage(); + virtual cTWPrintCmdLine::CmdLineArgs GetModeID() { return cTWPrintCmdLine::MODE_DBPRINT; } + virtual void SetConfigFile( TSTRING configFilePath ); +private: + cTWPrintReportMode_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Database Printing +/////////////////////////////////////////////////////////////////////////////// +class cTWPrintDBMode_i; +class cTWPrintDBMode : public iTWMode +{ +public: + cTWPrintDBMode(); + virtual ~cTWPrintDBMode(); + + void FillOutDBModeConfigInfo(cTWPrintDBMode_i* pModeInfo, const cConfigFile& cf); + + virtual void InitCmdLineParser( cCmdLineParser& parser); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage(); + virtual cTWPrintCmdLine::CmdLineArgs GetModeID() { return cTWPrintCmdLine::MODE_REPORTPRINT; } + virtual void SetConfigFile( TSTRING configFilePath ); +private: + cTWPrintDBMode_i* mpData; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Help Mode - a means for emitting mode-specific help. +/////////////////////////////////////////////////////////////////////////////// +class cTWPrintHelpMode_i; +class cTWPrintHelpMode : public iTWMode +{ +public: + cTWPrintHelpMode(); + virtual ~cTWPrintHelpMode(); + + virtual void InitCmdLineParser(cCmdLineParser& cmdLine); + virtual bool Init (const cConfigFile& cf, const cCmdLineParser& cmdLine); + virtual int Execute (cErrorQueue* pQueue); + virtual TSTRING GetModeUsage() { return _T(""); } + virtual cTWPrintCmdLine::CmdLineArgs GetModeID() { return cTWPrintCmdLine::MODE_HELP; } + virtual void SetConfigFile( TSTRING configFilePath ); +private: + cTWPrintHelpMode_i* mpData; +}; + + + +#endif// TWPRINTCMDLINE + diff --git a/src/twprint/twprinterrors.cpp b/src/twprint/twprinterrors.cpp new file mode 100644 index 0000000..412922a --- /dev/null +++ b/src/twprint/twprinterrors.cpp @@ -0,0 +1,51 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////// +// twprinterrors.cpp +// +// Registers all error strings in the twprint package +// + +#include "stdtwprint.h" +#include "twprinterrors.h" + +#include "core/errortable.h" +#include "twprintcmdline.h" + +TSS_BEGIN_ERROR_REGISTRATION( twprint ) + +TSS_REGISTER_ERROR( eTWPrintInvalidParamHelp(), _T("Invalid mode parameter to help:") ); +TSS_REGISTER_ERROR( eTWPrintInvalidReportLevel(), _T("Invalid reporting level specified, valid levels: [0-4]") ); +TSS_REGISTER_ERROR( eTWPrintInvalidReportLevelCfg(),_T("Invalid reporting level in configuration file, must be [0-4]") ); + +TSS_END_ERROR_REGISTRATION() + diff --git a/src/twprint/twprinterrors.h b/src/twprint/twprinterrors.h new file mode 100644 index 0000000..c5b1350 --- /dev/null +++ b/src/twprint/twprinterrors.h @@ -0,0 +1,46 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twprinterrors.h +// Date....: 6/18/99 +// Creator.: David Azari (azari) +// + +#ifndef __TWPRINTERRORS_H +#define __TWPRINTERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( twprint ) + +#endif//__TWPRINTERRORS + diff --git a/src/twprint/twprintmain.cpp b/src/twprint/twprintmain.cpp new file mode 100644 index 0000000..25375e9 --- /dev/null +++ b/src/twprint/twprintmain.cpp @@ -0,0 +1,249 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// twprintmain.cpp +// + +#include "stdtwprint.h" + +#include "twprintstrings.h" +#include "twprintcmdline.h" + +#include "core/error.h" +#include "core/cmdlineparser.h" +#include "core/errorbucketimpl.h" +#include "core/usernotifystdout.h" +#include "core/timebomb.h" + +#include "core/debug.h" + +#include "tw/twinit.h" +#include "tw/configfile.h" +#include "tw/twutil.h" +#include "tw/twstrings.h" + +#include "twprint.h" // package initialization + +#if IS_UNIX +#include "core/unixfsservices.h" +#include +#endif + +#include // for auto_ptr +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// terminate and unexpected handlers +// TODO: move these to a common library +/////////////////////////////////////////////////////////////////////////////// +void tw_terminate_handler() +{ + fputs("### Internal Error.\n### Terminate Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +void tw_unexpected_handler() +{ + fputs("### Internal Error.\n### Unexpected Exception Handler called.\n### Exiting...\n", stderr); + _exit(1); +} + +int __cdecl _tmain( int argc, const TCHAR* argv[ ] ) +{ + int ret = 0; + + + if (TimeBombExploded()) + return 1; + + cTWInit twInit; + + try + { + // set unexpected and terminate handlers + // Note: we do this before Init() in case it attempts to call these handlers + // TODO: move this into the Init() routine + + EXCEPTION_NAMESPACE set_terminate(tw_terminate_handler); + EXCEPTION_NAMESPACE set_unexpected(tw_unexpected_handler); + + twInit.Init( argv[0] ); + TSS_Dependency( cTWPrint ); + + // init twprint strings + // + + cDebug::SetDebugLevel(cDebug::D_DEBUG); + + + // **** let's try a new way of doing things! + // first, process the command line + if (argc < 2) + { + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + + ret = 1; + goto exit; + } + + // + // Display the version info... + // this is quick and dirty ... just the way I like it :-) -- mdb + // + if (_tcscmp(argv[1], _T("--version")) == 0) + { + TCOUT << TSS_GetString(cTW, tw::STR_VERSION_LONG) << std::endl; + ret = 0; + goto exit; + } + + // Next, set the mode... exit with error if now valid mode specified. + std::auto_ptr pMode(cTWPrintCmdLine::GetMode(argc, argv)); + if(! pMode.get()) + { + // no valid mode passed; GetMode will display an appropriate string (include usage statement) + ret = 1; + goto exit; + } + + cCmdLineParser cmdLine; + // Call InitCmdLineParser for this mode: + pMode->InitCmdLineParser(cmdLine); + + try + { + cmdLine.Parse(argc, argv); + } + catch( eError& e ) + { + cTWUtil::PrintErrorMsg(e); + TCERR << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + + ret = 1; + goto exit; + } + + #if IS_UNIX + // erase the command line + // TODO: it might be a good idea to move this to cTWUtil + int i; + for (i = 1; i < argc; ++i) + memset((char*)argv[i], 0, strlen(argv[i])*sizeof(char)); + #endif + + cCmdLineIter iter(cmdLine); + if (iter.SeekToArg(cTWPrintCmdLine::HELP)) + { + TCOUT << TSS_GetString(cTWPrint, twprint::STR_TWPRINT_VERSION) << std::endl; + TCOUT << TSS_GetString(cTW, tw::STR_VERSION) << std::endl; + // Output a specific usage statement for this mode. + TCOUT << pMode->GetModeUsage(); + ret = 1; + goto exit; + } + + // open up the config file, possibly using the passed in path + cConfigFile config; + cErrorReporter errorReporter; + + if( pMode->GetModeID() != cTWPrintCmdLine::MODE_HELP ) + { + try + { + //open cfg file + TSTRING cfgPath; + cTWUtil::OpenConfigFile(config, cmdLine, cTWPrintCmdLine::CFG_FILE, errorReporter, cfgPath); + pMode->SetConfigFile( cfgPath ); + } + catch(eError& error) + { + cTWUtil::PrintErrorMsg(error); + TCERR << TSS_GetString(cTW, tw::STR_ERR_TWCFG_CANT_READ) << std::endl; + ret = 1; + goto exit; + } + } + + // ok, now we can initialize the mode object and have it execute + if(! pMode->Init(config, cmdLine)) + { + // TODO -- Init should spit out the error msg... + // I don't think this error message is necessary + //TCERR << _T("Problem initializing twprint!") << std::endl; + TCERR << TSS_GetString(cTW, tw::STR_GET_HELP) << std::endl; + ret = 1; + goto exit; + } + ret = pMode->Execute( &twInit.errorQueue ); + + }//end try block + + catch (eError& error) + { + cTWUtil::PrintErrorMsg(error); + ASSERT(false); + ret = 1; + } + + catch (std::bad_alloc e) + { + TCERR << _T("*** Fatal exception: Out of memory "); + TCERR << _T("*** Exiting...\n"); + ret = 1; + } + + catch (std::exception e) + { + TCERR << _T("*** Fatal exception: "); + std::cerr << e.what() << std::endl; + TCERR << _T("*** Exiting...\n"); + ret = 1; + } + + /* + catch (...) + { + TCERR << _T("*** Fatal exception occurred.\n"); + TCERR << _T("*** Exiting...\n"); + } + */ + +exit: + + + return ret; + +}//end MAIN + diff --git a/src/twprint/twprintstrings.cpp b/src/twprint/twprintstrings.cpp new file mode 100644 index 0000000..740bb16 --- /dev/null +++ b/src/twprint/twprintstrings.cpp @@ -0,0 +1,86 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twprintstrings.cpp +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#include "stdtwprint.h" +#include "twprint.h" +#include "twprintstrings.h" + +TSS_BeginStringtable( cTWPrint ) + + TSS_StringEntry( twprint::STR_TWPRINT_USAGE_SUMMARY, + _T("Usage:\n") + _T("\n") + _T("Print Database: twprint [-m d|--print-dbfile] [options] [object1 [object2...]]\n") + _T("Print Report: twprint [-m r|--print-report] [options]\n") + _T("Type 'twprint [mode] --help' OR\n") + _T("'twprint --help mode [mode...]' OR\n") + _T("'twprint --help all' for extended help\n") + _T("\n") + ), + + TSS_StringEntry( twprint::STR_TWPRINT_HELP_PRINT_DATABASE, + _T("Print Database mode:\n") + _T(" -m d --print-dbfile\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -d database --dbfile database\n") + _T(" -L localkey --local-keyfile localkey\n") + _T("[object1 [object2 ...]\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twprint::STR_TWPRINT_HELP_PRINT_REPORT, + _T("Print Report mode:\n") + _T(" -m r --print-report\n") + _T(" -v --verbose\n") + _T(" -s --silent, --quiet\n") + _T(" -c cfgfile --cfgfile cfgfile\n") + _T(" -r report --twrfile report\n") + _T(" -L localkey --local-keyfile localkey\n") + _T(" -t { 0|1|2|3|4 } --report-level { 0|1|2|3|4 }\n") + _T("\n") + _T("The -v and -s options are mutually exclusive.\n") + _T("\n") + ), + + TSS_StringEntry( twprint::STR_TWPRINT_VERSION, _T("twprint: Tripwire database and report printer.\n") ), + +TSS_EndStringtable( cTWPrint ) + diff --git a/src/twprint/twprintstrings.h b/src/twprint/twprintstrings.h new file mode 100644 index 0000000..c9fca7c --- /dev/null +++ b/src/twprint/twprintstrings.h @@ -0,0 +1,55 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: twprintstrings.h +// Date....: 05/11/99 +// Creator.: Brian McFeely (bmcfeely) +// + +#ifndef __TWPRINTSTRINGS_H +#define __TWPRINTSTRINGS_H + +#include "twprint.h" // for: STRINGTABLE syntax + +//--Message Keys + +TSS_BeginStringIds( twprint ) + + STR_TWPRINT_USAGE_SUMMARY, + STR_TWPRINT_HELP_PRINT_REPORT, + STR_TWPRINT_HELP_PRINT_DATABASE, + STR_TWPRINT_VERSION + +TSS_EndStringIds( twprint ) + +#endif//__TWPRINTSTRINGS_H + diff --git a/src/util/Makefile.am b/src/util/Makefile.am new file mode 100644 index 0000000..8a4b234 --- /dev/null +++ b/src/util/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +INCLUDES = -I.. + +noinst_LIBRARIES = libutil.a +libutil_a_SOURCES = \ + fileutil.cpp stdutil.cpp stringencoder.cpp \ + util.cpp utilerrors.cpp utilstrings.cpp + +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libutil_a_OBJECTS) + $(RANLIB) ../../lib/libtripwire.a diff --git a/src/util/Makefile.in b/src/util/Makefile.in new file mode 100644 index 0000000..2d12d38 --- /dev/null +++ b/src/util/Makefile.in @@ -0,0 +1,400 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(libutil_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = src/util +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libutil_a_AR = $(AR) $(ARFLAGS) +libutil_a_LIBADD = +am_libutil_a_OBJECTS = fileutil.$(OBJEXT) stdutil.$(OBJEXT) \ + stringencoder.$(OBJEXT) util.$(OBJEXT) utilerrors.$(OBJEXT) \ + utilstrings.$(OBJEXT) +libutil_a_OBJECTS = $(am_libutil_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libutil_a_SOURCES) +DIST_SOURCES = $(libutil_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORE_CRYPT_O = @CORE_CRYPT_O@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ # This gets rid of the -I. so INCLUDES must be more explicit +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +path_to_sendmail = @path_to_sendmail@ +path_to_vi = @path_to_vi@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = foreign no-dependencies +INCLUDES = -I.. +noinst_LIBRARIES = libutil.a +libutil_a_SOURCES = \ + fileutil.cpp stdutil.cpp stringencoder.cpp \ + util.cpp utilerrors.cpp utilstrings.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/util/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/util/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libutil.a: $(libutil_a_OBJECTS) $(libutil_a_DEPENDENCIES) + -rm -f libutil.a + $(libutil_a_AR) libutil.a $(libutil_a_OBJECTS) $(libutil_a_LIBADD) + $(RANLIB) libutil.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +all: $(noinst_LIBRARIES) + $(AR) ru ../../lib/libtripwire.a $(libutil_a_OBJECTS) + $(RANLIB) ../../lib/libtripwire.a +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/util/fileutil.cpp b/src/util/fileutil.cpp new file mode 100644 index 0000000..2f01ce0 --- /dev/null +++ b/src/util/fileutil.cpp @@ -0,0 +1,274 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileutil.cpp +// +#include "stdutil.h" +#include "fileutil.h" + +#include "core/corestrings.h" +#include "utilstrings.h" + +#include "core/usernotify.h" +#include "core/fsservices.h" +#include "core/error.h" +#include "core/errorgeneral.h" +#include "core/file.h" +#include "core/errorbucketimpl.h" + +#include // for the FileExists() stuff + +#if IS_UNIX +#include +#include +#include +#include +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// TestFileExists +/////////////////////////////////////////////////////////////////////////////// +void cFileUtil::TestFileExists(const TSTRING& fileName) +{ + if(! cFileUtil::FileExists(fileName)) + { + TSTRING filenameText = TSS_GetString( cCore, core::STR_ERROR_FILENAME ); + filenameText.append(fileName); + filenameText.append(1, _T('\n')); + filenameText.append(iFSServices::GetInstance()->GetErrString()); + + throw eOpen(filenameText); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TestFileWritable +/////////////////////////////////////////////////////////////////////////////// +void cFileUtil::TestFileWritable(const TSTRING& fileName) +{ + if(! cFileUtil::FileWritable(fileName)) + { + TSTRING filenameText = TSS_GetString( cCore, core::STR_ERROR_FILENAME); + filenameText.append(fileName); + filenameText.append(1, _T('\n')); + filenameText.append(iFSServices::GetInstance()->GetErrString()); + + throw eOpenWrite(filenameText); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TestFileWritable +/////////////////////////////////////////////////////////////////////////////// +void cFileUtil::TestFileReadable(const TSTRING& fileName) +{ + if(! cFileUtil::FileReadable(fileName)) + { + TSTRING filenameText = TSS_GetString( cCore, core::STR_ERROR_FILENAME); + filenameText.append(fileName); + filenameText.append(1, _T('\n')); + filenameText.append(iFSServices::GetInstance()->GetErrString()); + + throw eOpenRead(filenameText); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// IsDir +/////////////////////////////////////////////////////////////////////////////// +bool cFileUtil::IsDir( const TSTRING& fileName ) +{ + cFSStatArgs s; + try + { + iFSServices::GetInstance()->Stat( fileName, s ); + } + catch( eFSServices ) + { + return false; + } + + return( s.mFileType == cFSStatArgs::TY_DIR ); +} + +bool cFileUtil::IsRegularFile( const TSTRING& fileName ) +{ + cFSStatArgs s; + try + { + iFSServices::GetInstance()->Stat( fileName, s); + } + catch( eFSServices ) + { + return false; + } + return (s.mFileType == cFSStatArgs::TY_FILE ); +} + +/////////////////////////////////////////////////////////////////////////////// +// FileExists +/////////////////////////////////////////////////////////////////////////////// +bool cFileUtil::FileExists(const TSTRING& fileName) +{ + return((_taccess(fileName.c_str(), F_OK) == 0) && !cFileUtil::IsDir(fileName)); +} + +/////////////////////////////////////////////////////////////////////////////// +// FileReadable +/////////////////////////////////////////////////////////////////////////////// +bool cFileUtil::FileReadable(const TSTRING& fileName) +{ + // TODO:BAM on Win32 systems, _taccess doesn't check DACL, + // so all files are really readable + return( _taccess( fileName.c_str(), R_OK ) == 0 ); +} + +/////////////////////////////////////////////////////////////////////////////// +// FileWritable +/////////////////////////////////////////////////////////////////////////////// +bool cFileUtil::FileWritable(const TSTRING& fileName) +{ + // if the file does not exist, but could be + // created then return true + if (_taccess(fileName.c_str(), F_OK) != 0) + { + // After some other attempts to see if we could create + // the file, it became easier to just to create the file + // and check for failure. + int fh; + if ((fh = _tcreat(fileName.c_str(), 0777)) == -1) + return false; + + close(fh); + if (_tunlink(fileName.c_str()) != 0) + ASSERT(false); + + return true; + } + else // file exists; make sure it is writable and not a dir + { + return((_taccess(fileName.c_str(), W_OK) == 0) && !cFileUtil::IsDir(fileName)); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// BackupFile +// +// Renames the file, if it exists, to an appropiate backup name for the OS. +// Prints warning and returns false if file backup fails, otherwise returns true. +// An eFile(ERR_FILE_WRITE_FAILED) will be thrown if the file is not writable. +// This is because we don't want to overwrite read-only files, which would happen +// if we were just renamed the file to a backup filename. +/////////////////////////////////////////////////////////////////////////////// +bool cFileUtil::BackupFile(const TSTRING& filename, bool printWarningOnFailure) // throw eFile() +{ + // if the file does not exist, no worries + if (!cFileUtil::FileExists(filename)) + return true; + + // if the file is not a regular file, it is not appropriate to back it up + if (!cFileUtil::IsRegularFile(filename)) + return true; + + // if it is not writeable, throw error + if (!cFileUtil::FileWritable(filename)) + { + // if this assert goes off, you didn't check that the file was writeable + // before calling BackupFile(). + ASSERT(false); + throw eFileWrite(filename, iFSServices::GetInstance()->GetErrString() ); + } + + TSTRING backup_filename = filename; + backup_filename += iFSServices::GetInstance()->GetStandardBackupExtension(); + + // remove the backup file if it exists. We ingore the return value from + // _tunlink(), problems removing the file will be caught by _trename(). + _tunlink(backup_filename.c_str()); + + // back up the file, preserving permissions and ownership, if possible + if (cFileUtil::Copy(filename.c_str(), backup_filename.c_str()) == false) + if (printWarningOnFailure && + iUserNotify::GetInstance()->GetVerboseLevel() >= iUserNotify::V_NORMAL) + { + TSTRING estr; + estr.assign(TSS_GetString( cUtil, util::STR_ERR2_BACKUP_FAILED1)); + estr.append(filename); + estr.append(TSS_GetString( cUtil, util::STR_ERR2_BACKUP_FAILED2)); + estr.append(backup_filename); + estr.append(TSS_GetString( cUtil, util::STR_ERR2_BACKUP_FAILED3)); + + cErrorReporter::PrintErrorMsg(eFileUtilBackup(estr, eError::NON_FATAL|eError::SUPRESS_THIRD_MSG)); + } + + return true; +} + +bool cFileUtil::Copy(const TSTRING& src_path, const TSTRING& dest_path) +{ +#if IS_UNIX + + enum { BUF_SIZE = 4096 }; + int8 buf[BUF_SIZE]; + int nBytesRead; + + cFile srcFile, destFile; + + srcFile.Open(src_path.c_str()); + // Create destination file. We'll fix the permissions later. + destFile.Open(dest_path.c_str(), cFile::OPEN_WRITE|cFile::OPEN_CREATE); + + for (int i = srcFile.GetSize(); i > 0; ) + { + nBytesRead = srcFile.Read(buf, BUF_SIZE); + destFile.Write(buf, nBytesRead); + i -= nBytesRead; + } + + struct stat srcStat; + stat(src_path.c_str(), &srcStat); + + // restore permissions and ownership + // don't worry if it fails. it's not mission-critical. + chmod( dest_path.c_str(), srcStat.st_mode ); + chown( dest_path.c_str(), srcStat.st_uid, srcStat.st_gid ); + + srcFile.Close(); + destFile.Close(); + +#endif + + return true; +} + + diff --git a/src/util/fileutil.h b/src/util/fileutil.h new file mode 100644 index 0000000..7f1240d --- /dev/null +++ b/src/util/fileutil.h @@ -0,0 +1,96 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileutil.h +// +#ifndef __FILEUTIL_H +#define __FILEUTIL_H + +#include "core/error.h" + +TSS_EXCEPTION( eFileUtil, eError ); +TSS_EXCEPTION( eFileUtilBackup, eFileUtil ); + +//----------------------------------------------------------------------------- +// cFileUtil +// +// collection of static utility functions related to file manipulation +//----------------------------------------------------------------------------- +// +// TODO -- remove unnecessary #includes from the top of twutil.h +// +class cFileUtil +{ +public: + //------------------------------------------------------------------------- + // File properties + //------------------------------------------------------------------------- + + static void TestFileExists(const TSTRING& fileName); //throw eError(); + // tests whether or not the file exists; throws eError suitable for cTWUtil::PrintErrorMsg() + static void TestFileWritable(const TSTRING& fileName); //throw eError(); + // tests whether or not the named file can be written to; throws eError suitable for cTWUtil::PrintErrorMsg() + static void TestFileReadable(const TSTRING& fileName); //throw eError(); + // tests whether or not the named file can be read from; throws eError suitable for cTWUtil::PrintErrorMsg() + static bool FileExists(const TSTRING& fileName); + // tests whether or not the file exists + static bool FileWritable(const TSTRING& fileName); + // tests whether or not the named file can be written to + // if the file does not exist, but can be created this function will return true + static bool FileReadable(const TSTRING& fileName); + // tests whether or not the named file can be read from + static bool IsDir( const TSTRING& fileName ); + // returns true if file is a dir + static bool IsRegularFile( const TSTRING& fileName ); + // returns true if file is a regular file + + //------------------------------------------------------------------------- + // File backup mechanism + //------------------------------------------------------------------------- + + static bool BackupFile(const TSTRING& filename, bool printWarningOnFailure = true); // throw eFile() + // Renames the file, if it exists, to an appropiate backup name for the OS. + // Prints warning and returns false if file backup fails, otherwise returns true. + // An eFileWrite will be thrown if the file is not writable. + // This is because we don't want to overwrite read-only files, which would happen + // if we were just renamed the file to a backup filename. + + //------------------------------------------------------------------------- + // File copy mechanism + //------------------------------------------------------------------------- + static bool Copy(const TSTRING& src, const TSTRING& dest); // throw eFile() + // copies the file from src to dest, preserving permissions. + +}; + +#endif //__FILEUTIL_H + diff --git a/src/util/fileutil_t.cpp b/src/util/fileutil_t.cpp new file mode 100644 index 0000000..227e93d --- /dev/null +++ b/src/util/fileutil_t.cpp @@ -0,0 +1,63 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// fileutil_t.cpp +// +// This is just to test my Copy() method. +// Feel free to add if you want. + +#include "stdutil.h" +#include "fileutil.h" +#include "core/debug.h" + +using namespace std; + +//========================================================================= +// FUNCTION CODE +//========================================================================= + +void TestFileUtil() +{ + + TSTRING source, dest; + + source = _T("/etc/disktab"); + dest = _T("/tmp/dest"); + bool blah = cFileUtil::Copy(source, dest); + (void)blah; + + +// TCOUT << _T("<") << wstr3 << _T(">") << std::endl; + + +} + diff --git a/src/util/miscutil.h b/src/util/miscutil.h new file mode 100644 index 0000000..dd1f69d --- /dev/null +++ b/src/util/miscutil.h @@ -0,0 +1,50 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// miscutil.h +// +#ifndef __MISCUTIL_H +#define __MISCUTIL_H + +//----------------------------------------------------------------------------- +// cMiscUtil +// +// Utility functions that don't fit anywhere else +//----------------------------------------------------------------------------- + +class cMiscUtil +{ +public: +}; + +#endif //__MISCUTIL_H + diff --git a/src/util/stdutil.cpp b/src/util/stdutil.cpp new file mode 100644 index 0000000..7d53ebd --- /dev/null +++ b/src/util/stdutil.cpp @@ -0,0 +1,41 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: stdutil.cpp +// Date....: 05/11/99 +// Creator.: rdifalco +// + +#include "stdutil.h" + + +// eof: stdutil.cpp diff --git a/src/util/stdutil.h b/src/util/stdutil.h new file mode 100644 index 0000000..2189466 --- /dev/null +++ b/src/util/stdutil.h @@ -0,0 +1,39 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stdutil.h +// +// Standard includes for util +// + +#include "core/stdcore.h" + diff --git a/src/util/stringencoder.cpp b/src/util/stringencoder.cpp new file mode 100644 index 0000000..61bc9d4 --- /dev/null +++ b/src/util/stringencoder.cpp @@ -0,0 +1,151 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stringencoder.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= +#include "stdutil.h" +#include "stringencoder.h" +#include "core/debug.h" + +//========================================================================= +// METHOD CODE +//========================================================================= + +////////////////////////////////////////////////////////////////////////////// +// cCharEncoder +////////////////////////////////////////////////////////////////////////////// + +void cCharEncoder::EncodeChar( TSTRING::const_iterator& i, TSTRING& strToAppendTo ) +{ + if( *i == mchEncodeMe ) + { + strToAppendTo += mchEncoded1; + strToAppendTo += mchEncoded2; + } + else if( *i == mchEncoded1 ) + { + strToAppendTo += mchEncoded1; + strToAppendTo += mchEncoded1; + } + else + { + strToAppendTo += *i; + } +} + +TCHAR cCharEncoder::DecodeChar( TSTRING::const_iterator& i, TSTRING::const_iterator& end ) +{ + ASSERT( i != end ); + + if( *i == mchEncodeMe ) + { + ASSERT( false ); + return _T('\0'); + } + else if( *i == mchEncoded1 ) + { + if( ++i == end ) + { + ASSERT( false ); + return _T('\0'); + } + else + { + if( *i == mchEncoded1 ) + return mchEncoded1 ; + else if( *i == mchEncoded2 ) + return mchEncodeMe ; + else + { + ASSERT( false ); + return _T('\0'); + } + } + } + else + return ( *i ); +} + +////////////////////////////////////////////////////////////////////////////// +// cStringEncoder +////////////////////////////////////////////////////////////////////////////// + +TSTRING& cStringEncoder::Encode( TSTRING& inAndOut ) +{ + TSTRING strOut; + Encode( inAndOut, strOut ); + inAndOut = strOut; + return inAndOut; +} + + +TSTRING& cStringEncoder::Encode( const TSTRING& in, TSTRING& out ) +{ + out.erase(); + // + // assume that out will approximately be the size of in + // + out.reserve( in.length() ); + + for( TSTRING::const_iterator i = in.begin(); i != in.end(); i++ ) + ce.EncodeChar( i, out ); + + return out; +} + +TSTRING& cStringEncoder::Unencode( TSTRING& inAndOut ) +{ + TSTRING strOut; + Unencode( inAndOut, strOut ); + inAndOut = strOut; + return inAndOut; +} + +TSTRING& cStringEncoder::Unencode( const TSTRING& in, TSTRING& out ) +{ + out.erase(); + // + // assume that out will approximately be the size of in + // + out.reserve( in.length() ); + + TSTRING::const_iterator end = in.end(); + for( TSTRING::const_iterator i = in.begin(); i != end; i++ ) + out += ce.DecodeChar( i, end ); + + return out; +} + diff --git a/src/util/stringencoder.h b/src/util/stringencoder.h new file mode 100644 index 0000000..eea4516 --- /dev/null +++ b/src/util/stringencoder.h @@ -0,0 +1,149 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stringencoder.h +// + +#ifndef __STRINGENCODER_H +#define __STRINGENCODER_H + +//========================================================================= +// INCLUDES +//========================================================================= + +#ifndef __TCHAR_H +#include "core/tchar.h" +#endif + +//========================================================================= +// DECLARATION OF CLASSES +//========================================================================= + +//////////////////////////////////////////////////////////////////////// +// class cCharEncoder +// +// encodes "chEncodeMe" to "chEncoded1,chEncoded2" +// encodes "chEncoded1" to "chEncoded1,chEncoded1" +// chEncoded2 will need no encoding +// +class cCharEncoder +{ +public: + cCharEncoder( TCHAR chEncodeMe, TCHAR chEncoded1, TCHAR chEncoded2 ); + + void EncodeChar( TSTRING::const_iterator& i, TSTRING& strToAppendTo ); + TCHAR DecodeChar( TSTRING::const_iterator& i, TSTRING::const_iterator& end ); + TCHAR GetEncodeChar(); + +private: + cCharEncoder(); + cCharEncoder( const cCharEncoder& ); + cCharEncoder& operator=( const cCharEncoder& ); + + TCHAR mchEncodeMe; + TCHAR mchEncoded1; + TCHAR mchEncoded2; +}; + +//////////////////////////////////////////////////////////////////////// +// class cStringEncoder +// +class cStringEncoder +{ +public: + cStringEncoder( TCHAR chEncodeMe, TCHAR chEncoded1, TCHAR chEncoded2 ); + + TSTRING& Encode( TSTRING& inAndOut ); + TSTRING& Encode( const TSTRING& in, TSTRING& out ); + // returns reference to out + + TSTRING& Unencode( TSTRING& inAndOut ); + TSTRING& Unencode( const TSTRING& in, TSTRING& out ); + // returns reference to out + + TCHAR GetEncodeChar(); + +private: + cStringEncoder(); + cStringEncoder( const cStringEncoder& ); + cStringEncoder& operator=( const cStringEncoder& ); + + cCharEncoder ce; +}; + +//////////////////////////////////////////////////////////////////////// +// class cQuoteEncoder +// +// convenience class that converts <"> -> <\"> and <\> -> <\\> +// +class cQuoteEncoder : public cStringEncoder +{ +public: + cQuoteEncoder(); +private: + cQuoteEncoder( const cQuoteEncoder& ); + cQuoteEncoder& operator=( const cQuoteEncoder& ); +}; + + +//========================================================================= +// INLINE FUNCTIONS +//========================================================================= + + +inline cCharEncoder::cCharEncoder( TCHAR chEncodeMe, TCHAR chEncoded1, TCHAR chEncoded2 ) + : mchEncodeMe( chEncodeMe ), mchEncoded1( chEncoded1 ), mchEncoded2( chEncoded2 ) +{ +} + +inline TCHAR cCharEncoder::GetEncodeChar() +{ + return mchEncodeMe; +} + +inline cStringEncoder::cStringEncoder( TCHAR chEncodeMe, TCHAR chEncoded1, TCHAR chEncoded2 ) + : ce( chEncodeMe, chEncoded1, chEncoded2 ) +{ +} + +inline TCHAR cStringEncoder::GetEncodeChar() +{ + return ce.GetEncodeChar(); +} + +inline cQuoteEncoder::cQuoteEncoder() + : cStringEncoder( _T('\"'), _T('\\'), _T('\"') ) +{ +} + +#endif //__STRINGENCODER_H + diff --git a/src/util/stringencoder_t.cpp b/src/util/stringencoder_t.cpp new file mode 100644 index 0000000..db25929 --- /dev/null +++ b/src/util/stringencoder_t.cpp @@ -0,0 +1,92 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +/////////////////////////////////////////////////////////////////////////////// +// stringencoder_t.cpp +// + +//========================================================================= +// INCLUDES +//========================================================================= + +#include "stdutil.h" +#include "stringencoder.h" + +//========================================================================= +// STANDARD LIBRARY INCLUDES +//========================================================================= + +#include + +//========================================================================= +// OTHER DIRECTIVES +//========================================================================= + +using namespace std; + +//========================================================================= +// UTIL FUNCTION PROTOTYES +//========================================================================= + +void OutputString( TSTRING& str ); + +//========================================================================= +// FUNCTION CODE +//========================================================================= + +void TestStringEncoder() +{ + TSTRING str = _T("this is a non-quoted string"); + TSTRING strQ = _T("here's a quote:\"and a slash:\\ "); + TSTRING strJQ = _T("\""); + TSTRING strJS = _T("\\"); + TSTRING strWeird = _T("\\\"\"\\\"\\\\\"\"\"\""); + + OutputString( str ); + OutputString( strQ ); + OutputString( strJQ ); + OutputString( strJS ); + OutputString( strWeird ); +} + +//========================================================================= +// UTIL FUNCTION CODE +//========================================================================= + +void OutputString( TSTRING& str ) +{ + cQuoteEncoder qe; + + TCOUT << _T("Plain string: <") << str << _T(">") << endl; + TCOUT << _T("Encoded string: <") << qe.Encode( str ) << _T(">") << endl; + TCOUT << _T("Decoded string: <") << qe.Unencode( str ) << _T(">") << endl << endl ; +} + diff --git a/src/util/util.cpp b/src/util/util.cpp new file mode 100644 index 0000000..23c2efe --- /dev/null +++ b/src/util/util.cpp @@ -0,0 +1,74 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: util.cpp +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// +#include "stdutil.h" +#include "util.h" +#include "utilerrors.h" + +TSS_ImplementPackage( cUtil ) + +cUtil::cUtil() +{ + TSS_Dependency( cCore ); + TSS_REGISTER_PKG_ERRORS( util ) +} + +//----------------------------------------------------------------------------- +// Test Suites (TODO: Put in util_t.cpp, no longer related to util.h) +//----------------------------------------------------------------------------- +// + +#ifdef TSS_TEST + +#include "test/utx.h" + +TSS_DeclareTestSuite( cDisplayEncoderTest ); +TSS_DeclareTestSuite( cCharEncoderTest ); + +// +// Add the test suites to the package test suite +// +TSS_BeginTestSuite( cUtil ) + + TSS_AddTestSuite( cDisplayEncoderTest ); + TSS_AddTestSuite( cCharEncoderTest ); + +TSS_EndTestSuite( cUtil ) + +#endif // #ifdef TSS_TEST + +// eof: util.cpp diff --git a/src/util/util.h b/src/util/util.h new file mode 100644 index 0000000..20adbdd --- /dev/null +++ b/src/util/util.h @@ -0,0 +1,54 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: util.h +// Date....: 05/11/99 +// Creator.: rdifalco +// +// + +#ifndef __UTIL_H +#define __UTIL_H + +#include "core/core.h" // for: cCore Strings + +TSS_BeginPackage( cUtil ) + + TSS_DECLARE_STRINGTABLE; + + public: + cUtil(); + +TSS_EndPackage( cUtil ) + +#endif//__UTIL_H + diff --git a/src/util/utilerrors.cpp b/src/util/utilerrors.cpp new file mode 100644 index 0000000..0427df2 --- /dev/null +++ b/src/util/utilerrors.cpp @@ -0,0 +1,53 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +////////////////////////////////////////////////////////////////////// +// utilerrors.cpp +// +// Registers all error strings in the util package +// + +#include "stdutil.h" +#include "utilerrors.h" + +#include "fileutil.h" + +TSS_BEGIN_ERROR_REGISTRATION( util ) + +// +// FileUtil +// + +TSS_REGISTER_ERROR( eFileUtil(), _T("File Util Error.") ) +TSS_REGISTER_ERROR( eFileUtilBackup(), _T("File Backup Failed.") ) + + +TSS_END_ERROR_REGISTRATION() diff --git a/src/util/utilerrors.h b/src/util/utilerrors.h new file mode 100644 index 0000000..10aa2c6 --- /dev/null +++ b/src/util/utilerrors.h @@ -0,0 +1,47 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: utilerrors.h +// Date....: 5/17/99 +// Creator.: Matthew Brinkley (brinkley) +// +// + +#ifndef __UTILERRORS_H +#define __UTILERRORS_H + +#include "core/errortable.h" + +TSS_DECLARE_ERROR_REGISTRATION( util ) + +#endif//__UTILERRORS_H + diff --git a/src/util/utilstrings.cpp b/src/util/utilstrings.cpp new file mode 100644 index 0000000..2c78e15 --- /dev/null +++ b/src/util/utilstrings.cpp @@ -0,0 +1,52 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: utilstrings.cpp +// Date....: 05/11/99 +// Creator.: rdifalco +// + +#include "stdutil.h" +#include "utilstrings.h" + + +TSS_BeginStringtable( cUtil ) + + TSS_StringEntry( util::STR_ERR_BACKUP_FAILED, _T("File Backup Failed.") ), + TSS_StringEntry( util::STR_ERR2_BACKUP_FAILED1, _T("Error backing up \"") ), + TSS_StringEntry( util::STR_ERR2_BACKUP_FAILED2, _T("\" to \"") ), + TSS_StringEntry( util::STR_ERR2_BACKUP_FAILED3, _T("\".") ) + +TSS_EndStringtable( cUtil ) + + +// eof: utilstrings.cpp diff --git a/src/util/utilstrings.h b/src/util/utilstrings.h new file mode 100644 index 0000000..0e37e21 --- /dev/null +++ b/src/util/utilstrings.h @@ -0,0 +1,56 @@ +// +// The developer of the original code and/or files is Tripwire, Inc. +// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, +// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights +// reserved. +// +// This program is free software. The contents of this file are subject +// to 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. You may redistribute it and/or modify it +// only in compliance with the GNU General Public License. +// +// This program is distributed in the hope that it will be useful. +// However, this program is distributed AS-IS WITHOUT ANY +// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS +// FOR A PARTICULAR PURPOSE. Please 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. +// +// Nothing in the GNU General Public License or any other license to use +// the code or files shall permit you to use Tripwire's trademarks, +// service marks, or other intellectual property without Tripwire's +// prior written consent. +// +// If you have any questions, please contact Tripwire, Inc. at either +// info@tripwire.org or www.tripwire.org. +// +// +// Name....: utilstrings.h +// Date....: 05/11/99 +// Creator.: rdifalco +// +// + +#ifndef __UTILSTRINGS_H +#define __UTILSTRINGS_H + +#include "util.h" // for TSS_BeginStringIds + + +TSS_BeginStringIds( util ) + + STR_ERR_BACKUP_FAILED, + STR_ERR2_BACKUP_FAILED1, + STR_ERR2_BACKUP_FAILED2, + STR_ERR2_BACKUP_FAILED3 + +TSS_EndStringIds( util ) + + +#endif//__UTILSTRINGS_H + diff --git a/tripwire.spec b/tripwire.spec new file mode 100644 index 0000000..e263006 --- /dev/null +++ b/tripwire.spec @@ -0,0 +1,332 @@ +%define path_to_vi /bin/vi +%define path_to_sendmail /usr/sbin/sendmail + +Name: tripwire +Version: 2.4.2.2 +Release: 1%{?dist} +Summary: IDS (Intrusion Detection System) + +License: GPL +Group: Applications/System +Source0: http://download.sourceforge.net/tripwire/tripwire-%{version}-src.tar.bz2 +Source1: tripwire.cron.in +Source3: tripwire.gif +Source4: twcfg.txt.in +Source5: tripwire-setup-keyfiles.in +Source6: twpol.txt.in +Source7: README.Fedora.in +Source9: License-Issues +URL: http://www.tripwire.org/ +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: openssl-devel +Requires(post): sed + +Patch1: tripwire-siggen-man8.patch + +%description +Tripwire is a very valuable security tool for Linux systems, if it is +installed to a clean system. Tripwire should be installed right after +the OS installation, and before you have connected your system to a +network (i.e., before any possibility exists that someone could alter +files on your system). + +When Tripwire is initially set up, it creates a database that records +certain file information. Then when it is run, it compares a designated +set of files and directories to the information stored in the database. +Added or deleted files are flagged and reported, as are any files that +have changed from their previously recorded state in the database. When +Tripwire is run against system files on a regular basis, any file +changes will be spotted when Tripwire is run. Tripwire will report the +changes, which will give system administrators a clue that they need to +enact damage control measures immediately if certain files have been +altered. + +%prep +%setup -q +%{__cp} -p %{SOURCE3} . + +%patch1 -p1 -b .siggen.manpage + +%build +%{__chmod} 755 configure +# RPM_OPT_FLAGS break the code (deadlock). +export CXXFLAGS="-O -Wall -pipe -g" +./configure -q \ + path_to_vi=%{path_to_vi} \ + path_to_sendmail=%{path_to_sendmail} \ + --prefix=/ \ + --sysconfdir=%{_sysconfdir}/tripwire \ + --sbindir=%{_sbindir} \ + --libdir=%{_var}/lib \ + --mandir=%{_mandir} + +%{__make} %{?_smp_mflags} + +%install +%{__rm} -fr ${RPM_BUILD_ROOT} + +# Install the binaries. +%{__mkdir_p} ${RPM_BUILD_ROOT}%{_sbindir} +%{__install} -p -m755 bin/siggen ${RPM_BUILD_ROOT}%{_sbindir} +%{__install} -p -m755 bin/tripwire ${RPM_BUILD_ROOT}%{_sbindir} +%{__install} -p -m755 bin/twadmin ${RPM_BUILD_ROOT}%{_sbindir} +%{__install} -p -m755 bin/twprint ${RPM_BUILD_ROOT}%{_sbindir} + +# Install the man pages. +%{__mkdir_p} ${RPM_BUILD_ROOT}%{_mandir}/{man4,man5,man8} +%{__install} -p -m644 man/man4/*.4 ${RPM_BUILD_ROOT}%{_mandir}/man4/ +%{__install} -p -m644 man/man5/*.5 ${RPM_BUILD_ROOT}%{_mandir}/man5/ +%{__install} -p -m644 man/man8/*.8 ${RPM_BUILD_ROOT}%{_mandir}/man8/ + +# Create configuration files from templates. +%{__rm} -fr _tmpcfg +%{__mkdir} _tmpcfg +for infile in %{SOURCE1} %{SOURCE4} %{SOURCE5} %{SOURCE6} %{SOURCE7} ; do + outfile=${infile##/*/} + outfile=${outfile%.*n} + cat ${infile} |\ + %{__sed} -e 's|@path_to_vi@|%{path_to_vi}|g' |\ + %{__sed} -e 's|@path_to_sendmail@|%{path_to_sendmail}|g' |\ + %{__sed} -e 's|@sysconfdir@|%{_sysconfdir}|g' |\ + %{__sed} -e 's|@sbindir@|%{_sbindir}|g' |\ + %{__sed} -e 's|@vardir@|%{_var}|g' >\ + _tmpcfg/${outfile} +done +%{__mv} _tmpcfg/{tripwire-setup-keyfiles,README.Fedora} . + +# Create the reports directory. +%{__install} -d -m700 ${RPM_BUILD_ROOT}%{_var}/lib/tripwire/report + +# Install the cron job. +%{__install} -d -m755 ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily +%{__install} -p -m755 _tmpcfg/tripwire.cron \ + ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/tripwire-check +%{__rm} _tmpcfg/tripwire.cron + +# Install configuration files. +%{__mkdir_p} ${RPM_BUILD_ROOT}%{_sysconfdir}/tripwire +for file in _tmpcfg/* ; do + %{__install} -p -m644 ${file} ${RPM_BUILD_ROOT}%{_sysconfdir}/tripwire +done + +# Install the keyfile setup script +%{__install} -p -m755 tripwire-setup-keyfiles ${RPM_BUILD_ROOT}%{_sbindir} + +# Fix permissions on documentation files. +%{__cp} -p %{SOURCE9} . +%{__chmod} 644 \ + ChangeLog COMMERCIAL COPYING TRADEMARK tripwire.gif \ + README.Fedora policy/policyguide.txt License-Issues + + +%clean +%{__rm} -rf ${RPM_BUILD_ROOT} + + +post +# Set the real hostname in twpol.txt +%{__sed} -i -e "s|localhost|$HOSTNAME|g" %{_sysconfdir}/tripwire/twpol.txt + + +%files +%defattr(0644,root,root,0755) +%doc ChangeLog COMMERCIAL COPYING TRADEMARK tripwire.gif +%doc README.Fedora policy/policyguide.txt License-Issues +%attr(0700,root,root) %dir %{_sysconfdir}/tripwire +%config(noreplace) %{_sysconfdir}/tripwire/twcfg.txt +%config(noreplace) %{_sysconfdir}/tripwire/twpol.txt +%attr(0755,root,root) %{_sysconfdir}/cron.daily/tripwire-check +%attr(0700,root,root) %dir %{_var}/lib/tripwire +%attr(0700,root,root) %dir %{_var}/lib/tripwire/report +%{_mandir}/*/* +%attr(0755,root,root) %{_sbindir}/* + + +%changelog +* Mon Nov 21 2011 Stephane Dudzinski 2.4.2.2 +- Updated spec file +- Updated version revision in reports and all +- Added experimental policy creation (see policy/policy_generator_readme.txt) +- Fixed report formating and sendmail issues +- Added Debian patches for crypto and hostnames +- Fixed compiling issue on recent GCC compilers (-fpermissive) + +* Wed Jul 13 2011 Stephane Dudzinski 2.4.2.1 +- Updated spec file to compile with 2.4.2.1 + +* Wed Feb 28 2007 Brandon Holbrook 2.4.1.1-1 +- Upgrade to upstream 2.4.1.1 (obsoletes gcc4 patch) +- Merge quickstart.txt into README.Fedora and fix doc bug (#161764) + +* Thu Dec 21 2006 Brandon Holbrook 2.4.0.1-4 +- Don't print anything at install time + +* Tue Dec 19 2006 Brandon Holbrook 2.4.0.1-3 +- Changed defattr to 644,755 +- removed BR: autoconf +- Inform users about README.Fedora instead of spamming the install + with catting the whole file + +* Wed Nov 15 2006 Brandon Holbrook 2.4.0.1-2 +- chmod'ed /etc/tripwire to 0700 +- Added sed to Requires(post) + +* Tue Aug 22 2006 Brandon Holbrook 2.4.0.1-1.4 +- Include COMMERCIAL file from upstream +- Print README.RPM on initial install +- Added _smp_mflags to make +- Removed ExclusiveArch: ix86 +- Replaced 2.3 with 2.4 in tripwire.txt + +* Tue Aug 22 2006 Brandon Holbrook 2.4.0.1-1.2 +- Updated to 2.4.0.1 + +* Fri Apr 7 2005 Michael Schwendt +- rebuilt + +* Tue Jun 15 2004 Keith G. Robertson-Turner 0:2.3.1-20.fdr.1 +- Revision bump to supersede Fedora Legacy +- Fixed a bogus entry in twpol.txt.in (modeprobe.conf -> modprobe.conf) + +* Thu Jun 10 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.9 +- Applied Paul Herman's patch to fix a format string vulnerability in + pipedmailmessage.cpp + +* Sun Feb 29 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.8 +- Default policy overhaul +- Spec cleanup + +* Sun Feb 22 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.7 +- Moved documentation data out of package description + +* Sat Feb 21 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.6 +- Removed explicit Buildrequires gcc-c++ + +* Fri Feb 20 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.5 +- Finally moved twinstall.sh from the sysconfdir to the sbindir, since + it is not a configuration file. Fixes Red Hat bug #61855 +- Renamed twinstall.sh to tripwire-setup-keyfiles, since the name is + misleading. It is setting up keyfiles, not installing an application +- Minor correction to twinstall.sh (now tripwire-setup-keyfiles), which + made an incorrect reference to the site key rather than the local key +- Long overdue default policy update +- Added explicit Buildrequires gcc-c++, to satisfy mach + +* Thu Feb 19 2004 Keith G. Robertson-Turner 0:2.3.1-18.fdr.4 +- Fixed siggen.8 man page, broken command synopsis syntax. Submitted by + doclifter +- Set real hostname in post, so Tripwire works first time, without + editing twpol.txt +- More accurate package summary +- Spec cleanup + +* Fri Nov 28 2003 Keith G. Robertson-Turner 0:2.3.1-18.fdr.3 +- Thanks to Michael Schwendt for really cleaning up the Spec file +- The remaining parts of the original tripwire-2.3.1-gcc3.patch have + now been implemented +- Debuginfo fully builds now + +* Thu Nov 27 2003 Keith G. Robertson-Turner 0:2.3.1-18.fdr.2 +- Removed version specific grep dependency, since grep >= 2.3 is common +- Added openssl-devel and autoconf to build dependencies +- The tripwire-jbj.patch is now confirmed merged with tw-20030919.patch +- Added RPM optimisation flags option, disabled by default since it + breaks the code +- Fixed file permissions of packaged files + +* Wed Nov 26 2003 Keith G. Robertson-Turner 0:2.3.1-18.fdr.1 +- Implemented Paul Herman's tw-20030919.patch +- Removed the fhs gcc3 and jbj patches, which are now broken/obsoleted + by the above +- Both the mkstemp and rfc822 patches are still implemented +- Build uses autoconf for now +- Spec file given complete overhaul for stricter compliance. More to do + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Sat Nov 16 2002 Jeff Johnson 2.3.1-16 +- rebuild from cvs. +- comment out debug messages to achieve compilation. +- include policyguide.txt (#72259). +- use mkstemp, not mktemp. + +* Fri Aug 02 2002 Mike A. Harris 2.3.1-14 +- Modified default sample twpol file to remove bogus warnings (#70502) + +* Fri Jun 21 2002 Tim Powers 2.3.1-13 +- automated rebuild + +* Sun May 26 2002 Tim Powers 2.3.1-12 +- automated rebuild + +* Wed May 22 2002 Mike A. Harris 2.3.1-11 +- Rebuilt in new build environment with gcc 3.1 + +* Tue Feb 26 2002 Mike A. Harris 2.3.1-9 +- Conditionalized gcc3 patch +- Added back the ExclusiveArch that is required but disappeared somewhere along + the line. +- Rebuild in new build environment + +* Thu Jan 31 2002 Mike A. Harris 2.3.1-7 +- Bump release and rebuild in new environment. +- (Elliot Lee) Add patch to make it build with gcc3. + +* Thu Aug 9 2001 Nalin Dahyabhai 2.3.1-5 +- define USE_FHS when USES_FHS is defined, so that the database winds up + in the right directory (#51332) +- update default twpol file to include files recently-added to the full + installation tree + +* Tue Jul 17 2001 Mike A. Harris 2.3.1-4 +- Applied bugfix for (#47276) to make tripwire email RFC822 compliant, using + patch in bugreport from Michael Schwendt + +* Tue Jul 10 2001 Mike A. Harris 2.3.1-3 +- Made package own dir /var/lib/tripwire + +* Mon Jun 25 2001 Nalin Dahyabhai +- update to 2.3.1-2 + +* Thu Mar 1 2001 Bill Nottingham +- rebuild, fix defattr. Weird. + +* Tue Feb 27 2001 Nalin Dahyabhai +- refresh from upstream +- modify the default policy to match the current tree more closely (#28744) +- make the text files 0644, not 0755 +- defattr for the sake of the docs + +* Wed Sep 20 2000 Nalin Dahyabhai +- change exclusivearch: i386 to exclusivearch: %%{ix86} (#17759) + +* Wed Aug 23 2000 Than Ngo +- remove copyleft information in specfile (Bug #16765) + +* Tue Aug 22 2000 Nalin Dahyabhai +- remove duplicate source files +- sync up description with specspo + +* Fri Aug 4 2000 Than Ngo +- remove Vendor and Distribution from specfile (Bug #15246) + +* Fri Aug 4 2000 Than Ngo +- starts tripwire --check if it was configured before. (Bug #15384) + +* Fri Aug 4 2000 Nalin Dahyabhai +- fix sense of checking for the database's existence in the cron job +- actually include twinstall.sh, twcfg.txt, twpol.txt + +* Thu Aug 3 2000 Than Ngo +- permission fix (bug #15246) + +* Mon Jul 31 2000 Nalin Dahyabhai +- add quickstart docs (Ed) +- tweak description text (Ed) + +* Thu Jul 20 2000 Nalin Dahyabhai +- update .spec file to follow RPM conventions +- add tripwire --check to cron.daily +